diff --git a/.gitattributes b/.gitattributes index cd4359ba3..35df6ca2f 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 -*.jpeg 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 0a19f3cee..de0707a93 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 000000000..562b12e16 --- /dev/null +++ b/3rdparty/.gitattributes @@ -0,0 +1 @@ +* -whitespace diff --git a/3rdparty/ffmpeg/ffmpeg_version.cmake b/3rdparty/ffmpeg/ffmpeg_version.cmake index 3cbcb394d..7bb8bab3f 100644 --- a/3rdparty/ffmpeg/ffmpeg_version.cmake +++ b/3rdparty/ffmpeg/ffmpeg_version.cmake @@ -1,5 +1,4 @@ set(HAVE_FFMPEG 1) -set(NEW_FFMPEG 1) set(HAVE_FFMPEG_CODEC 1) set(HAVE_FFMPEG_FORMAT 1) set(HAVE_FFMPEG_UTIL 1) @@ -9,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 9f11b52d6..2323af9ab 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 1928a5303..e98b28520 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 f62e5961f..6f28f2c55 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 c0237c1d0..010641ed1 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 2c235d824..5a145b25b 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 487258889..a524b743f 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 169d97e77..a1802f1ff 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 bdd09fb06..089c7e9e2 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 74bfdea5e..a9ffa4b0c 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 000000000..8ff7177ad 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 7c061d9ee..b6ce0d5a5 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 686bdfb61..635ce681a 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 5a5c23173..caacf39d4 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 694cfb80d..fff4a8069 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 c6cc8ab5f..311926555 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 94966c82e..7c18baf01 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 8251510c4..8bb093a3d 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 000000000..a05f17917 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 c8c9e2c57..b9500441a 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 6845d715d..d11dcf036 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 b148d1621..b06a6819f 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 000000000..844b806b9 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 d9400638b..0dd8904ac 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 cf2e9908c..105a19d0c 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 420ec818f..b01a4bd28 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 5468d206c..a59ae39b3 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 992331032..b90b82644 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 000000000..6607e5da8 Binary files /dev/null and b/3rdparty/lib/x86/libnative_camera_r4.3.0.so differ diff --git a/3rdparty/libpng/CMakeLists.txt b/3rdparty/libpng/CMakeLists.txt index d47dd53fc..141c9d151 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 000000000..6ca96392a --- /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 07b2b0b05..e7824b839 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 46fef61c7..cea2f906f 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 1e6bc0454..182f2833d 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 5c9cdd6ae..b5e68919c 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. @@ -20,20 +22,10 @@ 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,16 +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; + 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) { @@ -70,15 +62,12 @@ 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) { @@ -86,18 +75,13 @@ static int DecodeAlpha(const uint8_t* data, size_t data_size, if (unfilter_func != NULL) { // TODO(vikas): Implement on-the-fly decoding & filter mechanism to decode // and apply filter per image-row. - unfilter_func(width, height, width, decoded_data); + unfilter_func(width, height, width, output); } - // Construct raw_data (height x stride) from alpha data (height x width). - CopyPlane(decoded_data, width, output, stride, width, height); if (pre_processing == ALPHA_PREPROCESSED_LEVELS) { - ok = DequantizeLevels(decoded_data, width, height); + ok = DequantizeLevels(output, width, height); } } - if (method != ALPHA_NO_COMPRESSION) { - free(decoded_data); - } return ok; } @@ -105,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 c159f6f24..385571523 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 12c77bcbf..acdb15aaa 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 911c7ffc5..5f6a7d982 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. diff --git a/3rdparty/libwebp/dec/idec.c b/3rdparty/libwebp/dec/idec.c index 17810c838..5fbf49aaf 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; } diff --git a/3rdparty/libwebp/dec/io.c b/3rdparty/libwebp/dec/io.c index 594804c2e..63810b447 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 a3a5bdcfe..9a4b2d903 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 d54097af0..a4cc693db 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 82484e4c5..3f02efe43 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 253cb6b62..8632e48e5 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 diff --git a/3rdparty/libwebp/dec/vp8i.h b/3rdparty/libwebp/dec/vp8i.h index 1aa92385a..1d0d4077e 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. @@ -28,7 +30,7 @@ extern "C" { // version numbers #define DEC_MAJ_VERSION 0 #define DEC_MIN_VERSION 3 -#define DEC_REV_VERSION 0 +#define DEC_REV_VERSION 1 #define ONLY_KEYFRAME_CODE // to remove any code related to P-Frames @@ -276,6 +278,7 @@ struct VP8Decoder { // 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_; diff --git a/3rdparty/libwebp/dec/vp8l.c b/3rdparty/libwebp/dec/vp8l.c index 1665fe174..89b5b4bf6 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 @@ -625,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. @@ -667,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 @@ -903,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]); } @@ -1028,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); @@ -1070,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; } @@ -1079,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; @@ -1097,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); @@ -1143,6 +1200,7 @@ int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) { } int VP8LDecodeImage(VP8LDecoder* const dec) { + const size_t bytes_per_pixel = sizeof(uint32_t); VP8Io* io = NULL; WebPDecParams* params = NULL; @@ -1162,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 ee29eb5fa..543a76759 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 39d901888..97e79b64d 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. @@ -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. diff --git a/3rdparty/libwebp/dec/webpi.h b/3rdparty/libwebp/dec/webpi.h index 9349fcc7d..4ae0bfc5a 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 diff --git a/3rdparty/libwebp/demux/demux.c b/3rdparty/libwebp/demux/demux.c index 5d4dcf545..bd17ff7f6 100644 --- a/3rdparty/libwebp/demux/demux.c +++ b/3rdparty/libwebp/demux/demux.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. // ----------------------------------------------------------------------------- // // WebP container demux. @@ -27,7 +29,7 @@ extern "C" { #define DMUX_MAJ_VERSION 0 #define DMUX_MIN_VERSION 1 -#define DMUX_REV_VERSION 0 +#define DMUX_REV_VERSION 1 typedef struct { size_t start_; // start location of the data @@ -317,6 +319,7 @@ static ParseStatus ParseAnimationFrame( 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; } diff --git a/3rdparty/libwebp/dsp/cpu.c b/3rdparty/libwebp/dsp/cpu.c index 022873445..179901e10 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 758c6a572..2fbd6b1ac 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. diff --git a/3rdparty/libwebp/dsp/dec_neon.c b/3rdparty/libwebp/dsp/dec_neon.c index 5aff0d3fc..5dcd3b7e5 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. diff --git a/3rdparty/libwebp/dsp/dec_sse2.c b/3rdparty/libwebp/dsp/dec_sse2.c index 1cac1b843..6be94678e 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). diff --git a/3rdparty/libwebp/dsp/dsp.h b/3rdparty/libwebp/dsp/dsp.h index 933df60b4..01a95891f 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. diff --git a/3rdparty/libwebp/dsp/enc.c b/3rdparty/libwebp/dsp/enc.c index a6f05a5bb..552807ad9 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. @@ -142,9 +144,9 @@ static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { const int a1 = (d1 + d2); const int a2 = (d1 - d2); const int a3 = (d0 - d3); - tmp[0 + i * 4] = (a0 + a1) << 3; // 14b [-8160,8160] + 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) << 3; + tmp[2 + i * 4] = (a0 - a1) * 8; tmp[3 + i * 4] = (a3 * 2217 - a2 * 5352 + 937) >> 9; } for (i = 0; i < 4; ++i) { @@ -187,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; } } diff --git a/3rdparty/libwebp/dsp/enc_neon.c b/3rdparty/libwebp/dsp/enc_neon.c index 06b6b09cf..eb256e681 100644 --- a/3rdparty/libwebp/dsp/enc_neon.c +++ b/3rdparty/libwebp/dsp/enc_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 speed-critical encoding functions. @@ -322,7 +324,7 @@ static void FTransform(const uint8_t* src, const uint8_t* ref, "vmlal.s16 q11, d6, d17 \n" // c1*2217 + d1*5352 + 12000 "vmlsl.s16 q12, d6, d16 \n" // d1*2217 - c1*5352 + 51000 - "vmvn.s16 d4, d4 \n" + "vmvn d4, d4 \n" // !(d1 == 0) // op[4] = (c1*2217 + d1*5352 + 12000)>>16 "vshrn.s32 d1, q11, #16 \n" // op[4] += (d1!=0) @@ -363,19 +365,12 @@ static void FTransformWHT(const int16_t* in, int16_t* out) { "vld1.16 d2[3], [%[in]], %[kStep] \n" "vld1.16 d3[3], [%[in]], %[kStep] \n" - "vaddl.s16 q2, d0, d2 \n" - "vshl.s32 q2, q2, #2 \n" // a0=(in[0*16]+in[2*16])<<2 - "vaddl.s16 q3, d1, d3 \n" - "vshl.s32 q3, q3, #2 \n" // a1=(in[1*16]+in[3*16])<<2 - "vsubl.s16 q4, d1, d3 \n" - "vshl.s32 q4, q4, #2 \n" // a2=(in[1*16]-in[3*16])<<2 - "vsubl.s16 q5, d0, d2 \n" - "vshl.s32 q5, q5, #2 \n" // a3=(in[0*16]-in[2*16])<<2 + "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]) - "vceq.s32 q10, q2, #0 \n" - "vmvn.s32 q10, q10 \n" // (a0 != 0) - "vqadd.s32 q6, q2, q3 \n" // (a0 + a1) - "vqsub.s32 q6, q6, q10 \n" // (a0 + a1) + (a0 != 0) + "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 @@ -398,27 +393,10 @@ static void FTransformWHT(const int16_t* in, int16_t* out) { "vqsub.s32 q6, q3, q2 \n" // b2 = a3 - a2 "vqsub.s32 q7, q0, q1 \n" // b3 = a0 - a1 - "vmov.s32 q0, #3 \n" // q0 = 3 - - "vcgt.s32 q1, q4, #0 \n" // (b0>0) - "vqsub.s32 q2, q4, q1 \n" // (b0+(b0>0)) - "vqadd.s32 q3, q2, q0 \n" // (b0+(b0>0)+3) - "vshrn.s32 d18, q3, #3 \n" // (b0+(b0>0)+3) >> 3 - - "vcgt.s32 q1, q5, #0 \n" // (b1>0) - "vqsub.s32 q2, q5, q1 \n" // (b1+(b1>0)) - "vqadd.s32 q3, q2, q0 \n" // (b1+(b1>0)+3) - "vshrn.s32 d19, q3, #3 \n" // (b1+(b1>0)+3) >> 3 - - "vcgt.s32 q1, q6, #0 \n" // (b2>0) - "vqsub.s32 q2, q6, q1 \n" // (b2+(b2>0)) - "vqadd.s32 q3, q2, q0 \n" // (b2+(b2>0)+3) - "vshrn.s32 d20, q3, #3 \n" // (b2+(b2>0)+3) >> 3 - - "vcgt.s32 q1, q7, #0 \n" // (b3>0) - "vqsub.s32 q2, q7, q1 \n" // (b3+(b3>0)) - "vqadd.s32 q3, q2, q0 \n" // (b3+(b3>0)+3) - "vshrn.s32 d21, q3, #3 \n" // (b3+(b3>0)+3) >> 3 + "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" diff --git a/3rdparty/libwebp/dsp/enc_sse2.c b/3rdparty/libwebp/dsp/enc_sse2.c index 619e6c5ce..032e99076 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. @@ -453,6 +455,39 @@ 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 @@ -919,6 +954,7 @@ void VP8EncDspInitSSE2(void) { VP8EncQuantizeBlock = QuantizeBlockSSE2; VP8ITransform = ITransformSSE2; VP8FTransform = FTransformSSE2; + VP8FTransformWHT = FTransformWHTSSE2; VP8SSE16x16 = SSE16x16SSE2; VP8SSE16x8 = SSE16x8SSE2; VP8SSE8x8 = SSE8x8SSE2; diff --git a/3rdparty/libwebp/dsp/lossless.c b/3rdparty/libwebp/dsp/lossless.c index 080b3e632..e445924ed 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. @@ -1093,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) { @@ -1254,11 +1281,12 @@ static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst, while (src < src_end) { uint32_t argb = *src++; +#if !defined(__BIG_ENDIAN__) #if !defined(WEBP_REFERENCE_IMPLEMENTATION) -#if !defined(__BIG_ENDIAN__) && (defined(__i386__) || defined(__x86_64__)) +#if defined(__i386__) || defined(__x86_64__) __asm__ volatile("bswap %0" : "=r"(argb) : "0"(argb)); *(uint32_t*)dst = argb; -#elif !defined(__BIG_ENDIAN__) && defined(_MSC_VER) +#elif defined(_MSC_VER) argb = _byteswap_ulong(argb); *(uint32_t*)dst = argb; #else @@ -1267,11 +1295,17 @@ static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst, dst[2] = (argb >> 8) & 0xff; dst[3] = (argb >> 0) & 0xff; #endif -#else // WEBP_REFERENCE_IMPLEMENTATION +#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); } @@ -1325,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 0ac4ecb84..7490ec8ef 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); @@ -83,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 aea4964b6..80ba4f8a5 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. diff --git a/3rdparty/libwebp/dsp/upsampling_neon.c b/3rdparty/libwebp/dsp/upsampling_neon.c index 00e2f8928..d11889590 100644 --- a/3rdparty/libwebp/dsp/upsampling_neon.c +++ b/3rdparty/libwebp/dsp/upsampling_neon.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. // ----------------------------------------------------------------------------- // // NEON version of YUV to RGB upsampling functions. diff --git a/3rdparty/libwebp/dsp/upsampling_sse2.c b/3rdparty/libwebp/dsp/upsampling_sse2.c index ba075d11e..f31d04845 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. diff --git a/3rdparty/libwebp/dsp/yuv.c b/3rdparty/libwebp/dsp/yuv.c index f8988bae1..1a59f7449 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 diff --git a/3rdparty/libwebp/dsp/yuv.h b/3rdparty/libwebp/dsp/yuv.h index 126404b66..3844d8cab 100644 --- a/3rdparty/libwebp/dsp/yuv.h +++ b/3rdparty/libwebp/dsp/yuv.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. // ----------------------------------------------------------------------------- // // inline YUV<->RGB conversion function diff --git a/3rdparty/libwebp/enc/alpha.c b/3rdparty/libwebp/enc/alpha.c index aadf88fef..e636c9672 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. @@ -80,7 +82,7 @@ static int EncodeLossless(const uint8_t* const data, int width, int height, config.lossless = 1; config.method = effort_level; // impact is very small // Set a moderate default quality setting for alpha. - config.quality = 5.f * effort_level; + config.quality = 10.f * effort_level; assert(config.quality >= 0 && config.quality <= 100.f); ok = VP8LBitWriterInit(&tmp_bw, (width * height) >> 3); @@ -156,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, @@ -207,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) { @@ -234,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; @@ -262,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; } diff --git a/3rdparty/libwebp/enc/analysis.c b/3rdparty/libwebp/enc/analysis.c index 221e9d064..4ff3edd2a 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 diff --git a/3rdparty/libwebp/enc/backward_references.c b/3rdparty/libwebp/enc/backward_references.c index cf0278751..db4f430df 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) @@ -142,9 +144,10 @@ static void HashChainInsert(HashChain* const p, } static void GetParamsForHashChainFindCopy(int quality, int xsize, - int* window_size, int* iter_pos, - int* iter_limit) { + 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) @@ -152,77 +155,74 @@ static void GetParamsForHashChainFindCopy(int quality, int xsize, assert(xsize > 0); *window_size = (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE : max_window_size; - *iter_pos = 5 + (quality >> 3); - *iter_limit = -quality * iter_mult; + *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 base_position, 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[base_position]); - int prev_length = 0; - int64_t best_val = 0; - int best_length = 0; - int best_distance = 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; + uint64_t val; + uint32_t curr_length; + uint32_t distance; if (iter_pos < 0) { if (iter_pos < iter_limit || best_val >= 0xff0000) { break; } } --iter_pos; - if (best_length != 0 && - argb[pos + best_length - 1] != argb_start[best_length - 1]) { + 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 (base_position - pos < 9 * xsize) { - const int y = (base_position - pos) / xsize; - int x = (base_position - 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 = base_position - 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); } @@ -284,8 +284,8 @@ static int BackwardReferencesHashChain(int xsize, int ysize, if (!HashChainInit(hash_chain, pix_count)) goto Error; refs->size = 0; - GetParamsForHashChainFindCopy(quality, xsize, &window_size, &iter_pos, - &iter_limit); + 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; @@ -510,8 +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, &window_size, &iter_pos, - &iter_limit); + 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; @@ -645,8 +645,8 @@ static int BackwardReferencesHashChainFollowChosenPath( } refs->size = 0; - GetParamsForHashChainFindCopy(quality, xsize, &window_size, &iter_pos, - &iter_limit); + 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; @@ -785,7 +785,9 @@ int VP8LGetBackwardReferences(int width, int height, *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; diff --git a/3rdparty/libwebp/enc/backward_references.h b/3rdparty/libwebp/enc/backward_references.h index 8cb1a7a6d..b0d18135f 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) diff --git a/3rdparty/libwebp/enc/config.c b/3rdparty/libwebp/enc/config.c index bb88111bc..acf96b0f3 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 diff --git a/3rdparty/libwebp/enc/cost.c b/3rdparty/libwebp/enc/cost.c index 89b60ba61..d4916d7cd 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 diff --git a/3rdparty/libwebp/enc/cost.h b/3rdparty/libwebp/enc/cost.h index e264d3213..7d7c2c79a 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. diff --git a/3rdparty/libwebp/enc/filter.c b/3rdparty/libwebp/enc/filter.c index 7fb78a394..aae2723d1 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 95206185b..c56abed75 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 diff --git a/3rdparty/libwebp/enc/histogram.c b/3rdparty/libwebp/enc/histogram.c index 69e5fa36e..787ea5d18 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) diff --git a/3rdparty/libwebp/enc/histogram.h b/3rdparty/libwebp/enc/histogram.h index fe7cea6ff..583b5a4f8 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) diff --git a/3rdparty/libwebp/enc/iterator.c b/3rdparty/libwebp/enc/iterator.c index 86e473bcf..074665904 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 423127df6..fa8966099 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 1e51a8dc6..5aaa385d4 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, ... @@ -709,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]); @@ -809,7 +811,7 @@ int WebPPictureYUVAToARGB(WebPPicture* picture) { const uint8_t* const src = picture->a + y * picture->a_stride; int x; for (x = 0; x < width; ++x) { - argb_dst[x] = (argb_dst[x] & 0x00ffffffu) | (src[x] << 24); + argb_dst[x] = (argb_dst[x] & 0x00ffffffu) | ((uint32_t)src[x] << 24); } } } diff --git a/3rdparty/libwebp/enc/quant.c b/3rdparty/libwebp/enc/quant.c index dcfd4d16d..462d4e9e6 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 diff --git a/3rdparty/libwebp/enc/syntax.c b/3rdparty/libwebp/enc/syntax.c index e81fa2bed..b0f7676b4 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 diff --git a/3rdparty/libwebp/enc/token.c b/3rdparty/libwebp/enc/token.c index 4e2f6c00a..6a63371f7 100644 --- a/3rdparty/libwebp/enc/token.c +++ b/3rdparty/libwebp/enc/token.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. // ----------------------------------------------------------------------------- // // Paginated token buffer diff --git a/3rdparty/libwebp/enc/tree.c b/3rdparty/libwebp/enc/tree.c index 8b25e5e48..ecd8fb910 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 6aa3f436a..61d56be55 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. @@ -28,7 +30,7 @@ extern "C" { // version numbers #define ENC_MAJ_VERSION 0 #define ENC_MIN_VERSION 3 -#define ENC_REV_VERSION 0 +#define ENC_REV_VERSION 1 // intra prediction modes enum { B_DC_PRED = 0, // 4x4 modes diff --git a/3rdparty/libwebp/enc/vp8l.c b/3rdparty/libwebp/enc/vp8l.c index 5077167be..945870ca4 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. @@ -86,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]) { @@ -811,34 +813,66 @@ static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc, return err; } -// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel. -static void BundleColorMap(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; +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]; } - code |= row[x] << (8 + bit_depth * xsub); - dst[x >> xbits] = code; + VP8LBundleColorMap(row, width, xbits, dst); + src += src_stride; + dst += dst_stride; } } else { - for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8); + // 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; + } } } // 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* src = pic->argb; uint32_t* dst; @@ -864,20 +898,8 @@ static WebPEncodingError ApplyPalette(VP8LBitWriter* const bw, row = WebPSafeMalloc((uint64_t)width, sizeof(*row)); if (row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - const uint32_t pix = src[x]; - for (i = 0; i < palette_size; ++i) { - if (pix == palette[i]) { - row[x] = i; - break; - } - } - } - BundleColorMap(row, width, xbits, dst); - src += pic->argb_stride; - dst += enc->current_width_; - } + 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); @@ -899,13 +921,10 @@ static WebPEncodingError ApplyPalette(VP8LBitWriter* const bw, // ----------------------------------------------------------------------------- -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 eae90dd61..01f01f57e 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 20fbac4d0..d420d063e 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 @@ -386,9 +388,9 @@ int WebPEncode(const WebPConfig* config, WebPPicture* pic) { // Analysis is done, proceed to actual coding. ok = ok && VP8EncStartAlpha(enc); // possibly done in parallel if (!enc->use_tokens_) { - ok = VP8EncLoop(enc); + ok = ok && VP8EncLoop(enc); } else { - ok = VP8EncTokenLoop(enc); + ok = ok && VP8EncTokenLoop(enc); } ok = ok && VP8EncFinishAlpha(enc); #ifdef WEBP_EXPERIMENTAL_FEATURES diff --git a/3rdparty/libwebp/mux/muxedit.c b/3rdparty/libwebp/mux/muxedit.c index a486229c2..2d25a14d0 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. @@ -475,7 +477,7 @@ static WebPMuxError GetImageCanvasWidthHeight( int64_t image_area = 0; // 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; diff --git a/3rdparty/libwebp/mux/muxi.h b/3rdparty/libwebp/mux/muxi.h index 97b7f43dd..eaed558b4 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. @@ -26,7 +28,7 @@ extern "C" { #define MUX_MAJ_VERSION 0 #define MUX_MIN_VERSION 1 -#define MUX_REV_VERSION 0 +#define MUX_REV_VERSION 1 // Chunk object. typedef struct WebPChunk WebPChunk; diff --git a/3rdparty/libwebp/mux/muxinternal.c b/3rdparty/libwebp/mux/muxinternal.c index 3fa91f7d8..9543c0ee5 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. diff --git a/3rdparty/libwebp/mux/muxread.c b/3rdparty/libwebp/mux/muxread.c index 0e074fb2a..2179ccb79 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. diff --git a/3rdparty/libwebp/utils/bit_reader.c b/3rdparty/libwebp/utils/bit_reader.c index d6cfd8648..ab7a8273e 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 diff --git a/3rdparty/libwebp/utils/bit_reader.h b/3rdparty/libwebp/utils/bit_reader.h index ccf450c5d..588222b3b 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 @@ -194,6 +196,7 @@ static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) { #endif #else // BIG_ENDIAN bits = (bit_t)in_bits; + if (BITS != 8 * sizeof(bit_t)) bits >>= (8 * sizeof(bit_t) - BITS); #endif #ifndef USE_RIGHT_JUSTIFY br->value_ |= bits << (-br->bits_); diff --git a/3rdparty/libwebp/utils/bit_writer.c b/3rdparty/libwebp/utils/bit_writer.c index 671159cac..3827a13ad 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 f7ca08497..cbb095c1b 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 560f81db1..749db6128 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 13be629f3..e5a0bd6fd 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 9486355ab..eb5bb34f4 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 @@ -154,8 +156,7 @@ static void GradientUnfilter(int width, int height, int stride, uint8_t* 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) @@ -165,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; diff --git a/3rdparty/libwebp/utils/filters.h b/3rdparty/libwebp/utils/filters.h index 898252329..1f5fa164f 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 diff --git a/3rdparty/libwebp/utils/huffman.c b/3rdparty/libwebp/utils/huffman.c index 41529cc9d..0ba9d05cf 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 70220a67f..83a517ee6 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 2d680e3ec..96086663d 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) diff --git a/3rdparty/libwebp/utils/huffman_encode.h b/3rdparty/libwebp/utils/huffman_encode.h index cc3b38d33..0b81f470b 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 649aae655..42c7245d3 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]). diff --git a/3rdparty/libwebp/utils/quant_levels.h b/3rdparty/libwebp/utils/quant_levels.h index 9f85f34bf..2d90828df 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 diff --git a/3rdparty/libwebp/utils/quant_levels_dec.c b/3rdparty/libwebp/utils/quant_levels_dec.c index 95142b1b1..d93594b3b 100644 --- a/3rdparty/libwebp/utils/quant_levels_dec.c +++ b/3rdparty/libwebp/utils/quant_levels_dec.c @@ -1,8 +1,10 @@ // Copyright 2013 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. // ----------------------------------------------------------------------------- // // TODO(skal): implement gradient smoothing. diff --git a/3rdparty/libwebp/utils/quant_levels_dec.h b/3rdparty/libwebp/utils/quant_levels_dec.h index 470cf4790..589106765 100644 --- a/3rdparty/libwebp/utils/quant_levels_dec.h +++ b/3rdparty/libwebp/utils/quant_levels_dec.h @@ -1,8 +1,10 @@ // Copyright 2013 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 de-quantization utility diff --git a/3rdparty/libwebp/utils/rescaler.c b/3rdparty/libwebp/utils/rescaler.c index 61530cfef..e5ddc296a 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 diff --git a/3rdparty/libwebp/utils/rescaler.h b/3rdparty/libwebp/utils/rescaler.h index ef93d465f..aedce4625 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 a14af559d..b1615d0fb 100644 --- a/3rdparty/libwebp/utils/thread.c +++ b/3rdparty/libwebp/utils/thread.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. // ----------------------------------------------------------------------------- // // Multi-threaded worker diff --git a/3rdparty/libwebp/utils/thread.h b/3rdparty/libwebp/utils/thread.h index 9afe09679..13a61a4c8 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 diff --git a/3rdparty/libwebp/utils/utils.c b/3rdparty/libwebp/utils/utils.c index b1db2f9d6..7eb06105b 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 diff --git a/3rdparty/libwebp/utils/utils.h b/3rdparty/libwebp/utils/utils.h index e5d6d6309..e10aeeb9d 100644 --- a/3rdparty/libwebp/utils/utils.h +++ b/3rdparty/libwebp/utils/utils.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. // ----------------------------------------------------------------------------- // // Misc. common utility functions diff --git a/3rdparty/libwebp/webp/decode.h b/3rdparty/libwebp/webp/decode.h index 181eb1860..141f8618f 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. @@ -20,13 +22,13 @@ extern "C" { #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; -#if !(defined(__cplusplus) || defined(c_plusplus)) -typedef enum VP8StatusCode VP8StatusCode; -typedef enum WEBP_CSP_MODE WEBP_CSP_MODE; -#endif typedef struct WebPIDecoder WebPIDecoder; typedef struct WebPBitstreamFeatures WebPBitstreamFeatures; typedef struct WebPDecoderOptions WebPDecoderOptions; @@ -138,7 +140,7 @@ WEBP_EXTERN(uint8_t*) WebPDecodeYUVInto( // 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], ... -enum WEBP_CSP_MODE { +typedef enum WEBP_CSP_MODE { MODE_RGB = 0, MODE_RGBA = 1, MODE_BGR = 2, MODE_BGRA = 3, MODE_ARGB = 4, MODE_RGBA_4444 = 5, @@ -151,7 +153,7 @@ enum WEBP_CSP_MODE { // 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) { @@ -220,7 +222,7 @@ WEBP_EXTERN(void) WebPFreeDecBuffer(WebPDecBuffer* buffer); //------------------------------------------------------------------------------ // Enumeration of the status codes -enum VP8StatusCode { +typedef enum VP8StatusCode { VP8_STATUS_OK = 0, VP8_STATUS_OUT_OF_MEMORY, VP8_STATUS_INVALID_PARAM, @@ -229,7 +231,7 @@ enum VP8StatusCode { VP8_STATUS_SUSPENDED, VP8_STATUS_USER_ABORT, VP8_STATUS_NOT_ENOUGH_DATA -}; +} VP8StatusCode; //------------------------------------------------------------------------------ // Incremental decoding @@ -262,6 +264,12 @@ enum VP8StatusCode { // 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); diff --git a/3rdparty/libwebp/webp/demux.h b/3rdparty/libwebp/webp/demux.h index cfb4fdfe7..c7cd5d66d 100644 --- a/3rdparty/libwebp/webp/demux.h +++ b/3rdparty/libwebp/webp/demux.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. // ----------------------------------------------------------------------------- // // Demux API. @@ -53,11 +55,11 @@ extern "C" { #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; -#if !(defined(__cplusplus) || defined(c_plusplus)) -typedef enum WebPDemuxState WebPDemuxState; -typedef enum WebPFormatFeature WebPFormatFeature; -#endif typedef struct WebPIterator WebPIterator; typedef struct WebPChunkIterator WebPChunkIterator; @@ -70,11 +72,11 @@ WEBP_EXTERN(int) WebPGetDemuxVersion(void); //------------------------------------------------------------------------------ // Life of a Demux object -enum WebPDemuxState { +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( @@ -100,7 +102,7 @@ WEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux); //------------------------------------------------------------------------------ // Data/information extraction. -enum WebPFormatFeature { +typedef enum WebPFormatFeature { WEBP_FF_FORMAT_FLAGS, // Extended format flags present in the 'VP8X' chunk. WEBP_FF_CANVAS_WIDTH, WEBP_FF_CANVAS_HEIGHT, @@ -110,7 +112,7 @@ enum WebPFormatFeature { // 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() diff --git a/3rdparty/libwebp/webp/encode.h b/3rdparty/libwebp/webp/encode.h index fea8ee428..726992f57 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 @@ -20,12 +22,12 @@ extern "C" { #define WEBP_ENCODER_ABI_VERSION 0x0201 // MAJOR(8b) + MINOR(8b) -#if !(defined(__cplusplus) || defined(c_plusplus)) -typedef enum WebPImageHint WebPImageHint; -typedef enum WebPEncCSP WebPEncCSP; -typedef enum WebPPreset WebPPreset; -typedef enum WebPEncodingError WebPEncodingError; -#endif +// 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; @@ -77,13 +79,13 @@ WEBP_EXTERN(size_t) WebPEncodeLosslessBGRA(const uint8_t* bgra, // Coding parameters // Image characteristics hint for the underlying encoder. -enum WebPImageHint { +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 WEBP_HINT_GRAPH, // Discrete tone image (graph, map-tile etc). WEBP_HINT_LAST -}; +} WebPImageHint; // Compression parameters. struct WebPConfig { @@ -133,14 +135,14 @@ struct WebPConfig { // Enumerate some predefined settings for WebPConfig, depending on the type // of source picture. These presets are used when calling WebPConfigPreset(). -enum WebPPreset { +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 WEBP_PRESET_DRAWING, // hand or line drawing, with high-contrast details WEBP_PRESET_ICON, // small-sized colorful images WEBP_PRESET_TEXT // text-like -}; +} WebPPreset; // Internal, version-checked, entry point WEBP_EXTERN(int) WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int); @@ -230,7 +232,7 @@ WEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size, typedef int (*WebPProgressHook)(int percent, const WebPPicture* picture); // Color spaces. -enum WebPEncCSP { +typedef enum WebPEncCSP { // chroma sampling WEBP_YUV420 = 0, // 4:2:0 WEBP_YUV422 = 1, // 4:2:2 @@ -243,10 +245,10 @@ enum WebPEncCSP { WEBP_YUV444A = 6, WEBP_YUV400A = 7, // grayscale + alpha WEBP_CSP_ALPHA_BIT = 4 // bit that is set if alpha is present -}; +} WebPEncCSP; // Encoding error conditions. -enum WebPEncodingError { +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 @@ -259,7 +261,7 @@ enum WebPEncodingError { VP8_ENC_ERROR_FILE_TOO_BIG, // file is bigger than 4G VP8_ENC_ERROR_USER_ABORT, // abort request by user VP8_ENC_ERROR_LAST // list terminator. always last. -}; +} WebPEncodingError; // maximum width/height allowed (inclusive), in pixels #define WEBP_MAX_DIMENSION 16383 @@ -360,8 +362,9 @@ 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); @@ -392,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 a6f76d8d5..4c04b50c6 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. diff --git a/3rdparty/libwebp/webp/mux.h b/3rdparty/libwebp/webp/mux.h index 85a892270..b8c7dc62e 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. @@ -53,26 +55,26 @@ 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. -#if !(defined(__cplusplus) || defined(c_plusplus)) -typedef enum WebPMuxError WebPMuxError; -typedef enum WebPChunkId WebPChunkId; -#endif typedef struct WebPMuxFrameInfo WebPMuxFrameInfo; typedef struct WebPMuxAnimParams WebPMuxAnimParams; // Error codes -enum WebPMuxError { +typedef enum WebPMuxError { WEBP_MUX_OK = 1, WEBP_MUX_NOT_FOUND = 0, WEBP_MUX_INVALID_ARGUMENT = -1, WEBP_MUX_BAD_DATA = -2, WEBP_MUX_MEMORY_ERROR = -3, WEBP_MUX_NOT_ENOUGH_DATA = -4 -}; +} WebPMuxError; // IDs for different types of chunks. -enum WebPChunkId { +typedef enum WebPChunkId { WEBP_CHUNK_VP8X, // VP8X WEBP_CHUNK_ICCP, // ICCP WEBP_CHUNK_ANIM, // ANIM @@ -84,7 +86,7 @@ enum WebPChunkId { WEBP_CHUNK_XMP, // XMP WEBP_CHUNK_UNKNOWN, // Other chunks. WEBP_CHUNK_NIL -}; +} WebPChunkId; //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/webp/mux_types.h b/3rdparty/libwebp/webp/mux_types.h index 4006a5409..b8bce363e 100644 --- a/3rdparty/libwebp/webp/mux_types.h +++ b/3rdparty/libwebp/webp/mux_types.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. // ----------------------------------------------------------------------------- // // Data-types common to the mux and demux libraries. @@ -20,31 +22,31 @@ extern "C" { #endif -#if !(defined(__cplusplus) || defined(c_plusplus)) -typedef enum WebPFeatureFlags WebPFeatureFlags; -typedef enum WebPMuxAnimDispose WebPMuxAnimDispose; -#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. -enum WebPFeatureFlags { +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. -enum WebPMuxAnimDispose { +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. -typedef struct WebPData WebPData; struct WebPData { const uint8_t* bytes; size_t size; diff --git a/3rdparty/libwebp/webp/types.h b/3rdparty/libwebp/webp/types.h index 3e27190be..568d1f263 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 3d4cc689f..e10b94007 100644 --- a/3rdparty/openexr/CMakeLists.txt +++ b/3rdparty/openexr/CMakeLists.txt @@ -22,7 +22,7 @@ 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) diff --git a/3rdparty/tbb/.gitignore b/3rdparty/tbb/.gitignore index 601e1b265..69ce9ceb9 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 af1581349..4e510ffa3 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() @@ -123,13 +134,22 @@ file(GLOB lib_hdrs "${tbb_src_dir}/src/tbb/*.h") list(APPEND lib_srcs "${tbb_src_dir}/src/rml/client/rml_tbb.cpp") if (WIN32) - add_definitions(-D__TBB_DYNAMIC_LOAD_ENABLED=0 - -D__TBB_BUILD=1 - -D_UNICODE - -DUNICODE - -DWINAPI_FAMILY=WINAPI_FAMILY_APP - -DDO_ITT_NOTIFY=0 + 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 @@ -173,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 c2c643a1a..f22aabaef 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 6f1255ffe..5ca9d127e 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 ea4dfbe9d..6e9762676 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 9e4c2cbc8..696957705 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 fbac44d90..ce0299edd 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 ee3f281aa..d87659d03 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 ca55c6ea9..fae202ef8 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 3493d34d4..bf4538eb2 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 27cb3428e..aa767fbf6 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 981aff17c..f3833c2e4 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 2f1d60b43..bda59ceb6 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 47418a1e1..870f89bb4 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 abcd7c45e..44d89cf24 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 8c32b214b..1fd7759ef 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 ad98be3a5..242e9493d 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 1e4e14045..6528fb4df 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 3edf3acdb..3e0c7672a 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 65e0d3b72..23d2ebef0 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 4e3dcc6ae..24ab06b1c 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 9cb3be0c3..c795ad3ff 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() @@ -126,10 +110,10 @@ endif() 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)) @@ -200,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.*) ) @@ -214,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 ) # ---------------------------------------------------------------------------- @@ -289,10 +265,6 @@ 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 @@ -308,21 +280,10 @@ set(OPENCV_EXTRA_MODULES_PATH "" CACHE PATH "Where to look for additional OpenCV # ---------------------------------------------------------------------------- # 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 @@ -366,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) @@ -383,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() @@ -502,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: @@ -608,6 +568,16 @@ 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: ") @@ -644,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})") @@ -749,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) @@ -839,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_NUMPY_INCLUDE_DIR 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 ========================== @@ -870,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 ========================== @@ -895,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 0799dff89..000000000 --- a/README +++ /dev/null @@ -1,17 +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 - -Please read before starting work on a pull request: - http://code.opencv.org/projects/opencv/wiki/How_to_contribute - -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. diff --git a/README.md b/README.md new file mode 100644 index 000000000..403f118ee --- /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/android.toolchain.cmake b/android/android.toolchain.cmake deleted file mode 100644 index 9db174a13..000000000 --- a/android/android.toolchain.cmake +++ /dev/null @@ -1,1747 +0,0 @@ -message(STATUS "Android toolchain was moved to platfroms/android!") -message(STATUS "This file is depricated and will be removed!") - -# Copyright (c) 2010-2011, Ethan Rublee -# Copyright (c) 2011-2013, Andrey Kamaev -# 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. The name of the copyright holders 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. - -# ------------------------------------------------------------------------------ -# Android CMake toolchain file, for use with the Android NDK r5-r8 -# Requires cmake 2.6.3 or newer (2.8.5 or newer is recommended). -# See home page: https://github.com/taka-no-me/android-cmake -# -# The file is mantained by the OpenCV project. The latest version can be get at -# http://code.opencv.org/projects/opencv/repository/revisions/master/changes/android/android.toolchain.cmake -# -# Usage Linux: -# $ export ANDROID_NDK=/absolute/path/to/the/android-ndk -# $ mkdir build && cd build -# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. -# $ make -j8 -# -# Usage Linux (using standalone toolchain): -# $ export ANDROID_STANDALONE_TOOLCHAIN=/absolute/path/to/android-toolchain -# $ mkdir build && cd build -# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. -# $ make -j8 -# -# Usage Windows: -# You need native port of make to build your project. -# Android NDK r7 (or newer) already has make.exe on board. -# For older NDK you have to install it separately. -# For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm -# -# $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk -# $ mkdir build && cd build -# $ cmake.exe -G"MinGW Makefiles" -# -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake -# -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" .. -# $ cmake.exe --build . -# -# -# Options (can be set as cmake parameters: -D=): -# ANDROID_NDK=/opt/android-ndk - path to the NDK root. -# Can be set as environment variable. Can be set only at first cmake run. -# -# ANDROID_STANDALONE_TOOLCHAIN=/opt/android-toolchain - path to the -# standalone toolchain. This option is not used if full NDK is found -# (ignored if ANDROID_NDK is set). -# Can be set as environment variable. Can be set only at first cmake run. -# -# ANDROID_ABI=armeabi-v7a - specifies the target Application Binary -# Interface (ABI). This option nearly matches to the APP_ABI variable -# used by ndk-build tool from Android NDK. -# -# Possible targets are: -# "armeabi" - matches to the NDK ABI with the same name. -# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. -# "armeabi-v7a" - matches to the NDK ABI with the same name. -# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. -# "armeabi-v7a with NEON" - same as armeabi-v7a, but -# sets NEON as floating-point unit -# "armeabi-v7a with VFPV3" - same as armeabi-v7a, but -# sets VFPV3 as floating-point unit (has 32 registers instead of 16). -# "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP. -# "x86" - matches to the NDK ABI with the same name. -# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. -# "mips" - matches to the NDK ABI with the same name -# (It is not tested on real devices by the authos of this toolchain) -# See ${ANDROID_NDK}/docs/CPU-ARCH-ABIS.html for the documentation. -# -# ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for. -# Option is read-only when standalone toolchain is used. -# -# ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.6 - the name of compiler -# toolchain to be used. The list of possible values depends on the NDK -# version. For NDK r8c the possible values are: -# -# * arm-linux-androideabi-4.4.3 -# * arm-linux-androideabi-4.6 -# * arm-linux-androideabi-clang3.1 -# * mipsel-linux-android-4.4.3 -# * mipsel-linux-android-4.6 -# * mipsel-linux-android-clang3.1 -# * x86-4.4.3 -# * x86-4.6 -# * x86-clang3.1 -# -# ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions -# instead of Thumb. Is not available for "x86" (inapplicable) and -# "armeabi-v6 with VFP" (is forced to be ON) ABIs. -# -# ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker -# errors even if they are not used. -# -# ANDROID_SO_UNDEFINED=OFF - set ON to allow undefined symbols in shared -# libraries. Automatically turned for NDK r5x and r6x due to GLESv2 -# problems. -# -# LIBRARY_OUTPUT_PATH_ROOT=${CMAKE_SOURCE_DIR} - where to output binary -# files. See additional details below. -# -# ANDROID_SET_OBSOLETE_VARIABLES=ON - if set, then toolchain defines some -# obsolete variables which were used by previous versions of this file for -# backward compatibility. -# -# ANDROID_STL=gnustl_static - specify the runtime to use. -# -# Possible values are: -# none -> Do not configure the runtime. -# system -> Use the default minimal system C++ runtime library. -# Implies -fno-rtti -fno-exceptions. -# Is not available for standalone toolchain. -# system_re -> Use the default minimal system C++ runtime library. -# Implies -frtti -fexceptions. -# Is not available for standalone toolchain. -# gabi++_static -> Use the GAbi++ runtime as a static library. -# Implies -frtti -fno-exceptions. -# Available for NDK r7 and newer. -# Is not available for standalone toolchain. -# gabi++_shared -> Use the GAbi++ runtime as a shared library. -# Implies -frtti -fno-exceptions. -# Available for NDK r7 and newer. -# Is not available for standalone toolchain. -# stlport_static -> Use the STLport runtime as a static library. -# Implies -fno-rtti -fno-exceptions for NDK before r7. -# Implies -frtti -fno-exceptions for NDK r7 and newer. -# Is not available for standalone toolchain. -# stlport_shared -> Use the STLport runtime as a shared library. -# Implies -fno-rtti -fno-exceptions for NDK before r7. -# Implies -frtti -fno-exceptions for NDK r7 and newer. -# Is not available for standalone toolchain. -# gnustl_static -> Use the GNU STL as a static library. -# Implies -frtti -fexceptions. -# gnustl_shared -> Use the GNU STL as a shared library. -# Implies -frtti -fno-exceptions. -# Available for NDK r7b and newer. -# Silently degrades to gnustl_static if not available. -# -# ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on -# chosen runtime. If disabled, then the user is responsible for settings -# these options. -# -# What?: -# android-cmake toolchain searches for NDK/toolchain in the following order: -# ANDROID_NDK - cmake parameter -# ANDROID_NDK - environment variable -# ANDROID_STANDALONE_TOOLCHAIN - cmake parameter -# ANDROID_STANDALONE_TOOLCHAIN - environment variable -# ANDROID_NDK - default locations -# ANDROID_STANDALONE_TOOLCHAIN - default locations -# -# Make sure to do the following in your scripts: -# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" ) -# SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" ) -# The flags will be prepopulated with critical flags, so don't loose them. -# Also be aware that toolchain also sets configuration-specific compiler -# flags and linker flags. -# -# ANDROID and BUILD_ANDROID will be set to true, you may test any of these -# variables to make necessary Android-specific configuration changes. -# -# Also ARMEABI or ARMEABI_V7A or X86 or MIPS will be set true, mutually -# exclusive. NEON option will be set true if VFP is set to NEON. -# -# LIBRARY_OUTPUT_PATH_ROOT should be set in cache to determine where Android -# libraries will be installed. -# Default is ${CMAKE_SOURCE_DIR}, and the android libs will always be -# under the ${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME} -# (depending on the target ABI). This is convenient for Android packaging. -# -# Change Log: -# - initial version December 2010 -# - April 2011 -# [+] added possibility to build with NDK (without standalone toolchain) -# [+] support cross-compilation on Windows (native, no cygwin support) -# [+] added compiler option to force "char" type to be signed -# [+] added toolchain option to compile to 32-bit ARM instructions -# [+] added toolchain option to disable SWIG search -# [+] added platform "armeabi-v7a with VFPV3" -# [~] ARM_TARGETS renamed to ARM_TARGET -# [+] EXECUTABLE_OUTPUT_PATH is set by toolchain (required on Windows) -# [~] Fixed bug with ANDROID_API_LEVEL variable -# [~] turn off SWIG search if it is not found first time -# - May 2011 -# [~] ANDROID_LEVEL is renamed to ANDROID_API_LEVEL -# [+] ANDROID_API_LEVEL is detected by toolchain if not specified -# [~] added guard to prevent changing of output directories on the first -# cmake pass -# [~] toolchain exits with error if ARM_TARGET is not recognized -# - June 2011 -# [~] default NDK path is updated for version r5c -# [+] variable CMAKE_SYSTEM_PROCESSOR is set based on ARM_TARGET -# [~] toolchain install directory is added to linker paths -# [-] removed SWIG-related stuff from toolchain -# [+] added macro find_host_package, find_host_program to search -# packages/programs on the host system -# [~] fixed path to STL library -# - July 2011 -# [~] fixed options caching -# [~] search for all supported NDK versions -# [~] allowed spaces in NDK path -# - September 2011 -# [~] updated for NDK r6b -# - November 2011 -# [*] rewritten for NDK r7 -# [+] x86 toolchain support (experimental) -# [+] added "armeabi-v6 with VFP" ABI for ARMv6 processors. -# [~] improved compiler and linker flags management -# [+] support different build flags for Release and Debug configurations -# [~] by default compiler flags the same as used by ndk-build (but only -# where reasonable) -# [~] ANDROID_NDK_TOOLCHAIN_ROOT is splitted to ANDROID_STANDALONE_TOOLCHAIN -# and ANDROID_TOOLCHAIN_ROOT -# [~] ARM_TARGET is renamed to ANDROID_ABI -# [~] ARMEABI_NDK_NAME is renamed to ANDROID_NDK_ABI_NAME -# [~] ANDROID_API_LEVEL is renamed to ANDROID_NATIVE_API_LEVEL -# - January 2012 -# [+] added stlport_static support (experimental) -# [+] added special check for cygwin -# [+] filtered out hidden files (starting with .) while globbing inside NDK -# [+] automatically applied GLESv2 linkage fix for NDK revisions 5-6 -# [+] added ANDROID_GET_ABI_RAWNAME to get NDK ABI names by CMake flags -# - February 2012 -# [+] updated for NDK r7b -# [~] fixed cmake try_compile() command -# [~] Fix for missing install_name_tool on OS X -# - March 2012 -# [~] fixed incorrect C compiler flags -# [~] fixed CMAKE_SYSTEM_PROCESSOR change on ANDROID_ABI change -# [+] improved toolchain loading speed -# [+] added assembler language support (.S) -# [+] allowed preset search paths and extra search suffixes -# - April 2012 -# [+] updated for NDK r7c -# [~] fixed most of problems with compiler/linker flags and caching -# [+] added option ANDROID_FUNCTION_LEVEL_LINKING -# - May 2012 -# [+] updated for NDK r8 -# [+] added mips architecture support -# - August 2012 -# [+] updated for NDK r8b -# [~] all intermediate files generated by toolchain are moved to CMakeFiles -# [~] libstdc++ and libsupc are removed from explicit link libraries -# [+] added CCache support (via NDK_CCACHE environment or cmake variable) -# [+] added gold linker support for NDK r8b -# [~] fixed mips linker flags for NDK r8b -# - September 2012 -# [+] added NDK release name detection (see ANDROID_NDK_RELEASE) -# [+] added support for all C++ runtimes from NDK -# (system, gabi++, stlport, gnustl) -# [+] improved warnings on known issues of NDKs -# [~] use gold linker as default if available (NDK r8b) -# [~] globally turned off rpath -# [~] compiler options are aligned with NDK r8b -# - October 2012 -# [~] fixed C++ linking: explicitly link with math library (OpenCV #2426) -# - November 2012 -# [+] updated for NDK r8c -# [+] added support for clang compiler -# - December 2012 -# [+] suppress warning about unused CMAKE_TOOLCHAIN_FILE variable -# [+] adjust API level to closest compatible as NDK does -# [~] fixed ccache full path search -# [+] updated for NDK r8d -# [~] compiler options are aligned with NDK r8d -# - March 2013 -# [+] updated for NDK r8e (x86 version) -# [+] support x86_64 version of NDK -# - April 2013 -# [+] support non-release NDK layouts (from Linaro git and Android git) -# [~] automatically detect if explicit link to crtbegin_*.o is needed -# ------------------------------------------------------------------------------ - -cmake_minimum_required( VERSION 2.6.3 ) - -if( DEFINED CMAKE_CROSSCOMPILING ) - # subsequent toolchain loading is not really needed - return() -endif() - -if( CMAKE_TOOLCHAIN_FILE ) - # touch toolchain variable only to suppress "unused variable" warning -endif() - -get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE ) -if( _CMAKE_IN_TRY_COMPILE ) - include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL ) -endif() - -# this one is important -set( CMAKE_SYSTEM_NAME Linux ) -# this one not so much -set( CMAKE_SYSTEM_VERSION 1 ) - -# rpath makes low sence for Android -set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." ) - -set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" ) -if(NOT DEFINED ANDROID_NDK_SEARCH_PATHS) - if( CMAKE_HOST_WIN32 ) - file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS ) - set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}/android-ndk" "$ENV{SystemDrive}/NVPACK/android-ndk" ) - else() - file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS ) - set( ANDROID_NDK_SEARCH_PATHS /opt/android-ndk "${ANDROID_NDK_SEARCH_PATHS}/NVPACK/android-ndk" ) - endif() -endif() -if(NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH) - set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain ) -endif() - -set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" ) -set( ANDROID_SUPPORTED_ABIS_x86 "x86" ) -set( ANDROID_SUPPORTED_ABIS_mipsel "mips" ) - -set( ANDROID_DEFAULT_NDK_API_LEVEL 8 ) -set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 ) -set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 ) - - -macro( __LIST_FILTER listvar regex ) - if( ${listvar} ) - foreach( __val ${${listvar}} ) - if( __val MATCHES "${regex}" ) - list( REMOVE_ITEM ${listvar} "${__val}" ) - endif() - endforeach() - endif() -endmacro() - -macro( __INIT_VARIABLE var_name ) - set( __test_path 0 ) - foreach( __var ${ARGN} ) - if( __var STREQUAL "PATH" ) - set( __test_path 1 ) - break() - endif() - endforeach() - if( __test_path AND NOT EXISTS "${${var_name}}" ) - unset( ${var_name} CACHE ) - endif() - if( "${${var_name}}" STREQUAL "" ) - set( __values 0 ) - foreach( __var ${ARGN} ) - if( __var STREQUAL "VALUES" ) - set( __values 1 ) - elseif( NOT __var STREQUAL "PATH" ) - set( __obsolete 0 ) - if( __var MATCHES "^OBSOLETE_.*$" ) - string( REPLACE "OBSOLETE_" "" __var "${__var}" ) - set( __obsolete 1 ) - endif() - if( __var MATCHES "^ENV_.*$" ) - string( REPLACE "ENV_" "" __var "${__var}" ) - set( __value "$ENV{${__var}}" ) - elseif( DEFINED ${__var} ) - set( __value "${${__var}}" ) - else() - if( __values ) - set( __value "${__var}" ) - else() - set( __value "" ) - endif() - endif() - if( NOT "${__value}" STREQUAL "" ) - if( __test_path ) - if( EXISTS "${__value}" ) - file( TO_CMAKE_PATH "${__value}" ${var_name} ) - if( __obsolete AND NOT _CMAKE_IN_TRY_COMPILE ) - message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." ) - endif() - break() - endif() - else() - set( ${var_name} "${__value}" ) - if( __obsolete AND NOT _CMAKE_IN_TRY_COMPILE ) - message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." ) - endif() - break() - endif() - endif() - endif() - endforeach() - unset( __value ) - unset( __values ) - unset( __obsolete ) - elseif( __test_path ) - file( TO_CMAKE_PATH "${${var_name}}" ${var_name} ) - endif() - unset( __test_path ) -endmacro() - -macro( __DETECT_NATIVE_API_LEVEL _var _path ) - SET( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*$" ) - FILE( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" ) - if( NOT __apiFileContent ) - message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." ) - endif() - string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" ) - unset( __apiFileContent ) - unset( __ndkApiLevelRegex ) -endmacro() - -macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root ) - if( EXISTS "${_root}" ) - file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" ) - __LIST_FILTER( __gccExePath "^[.].*" ) - list( LENGTH __gccExePath __gccExePathsCount ) - if( NOT __gccExePathsCount EQUAL 1 AND NOT _CMAKE_IN_TRY_COMPILE ) - message( WARNING "Could not determine machine name for compiler from ${_root}" ) - set( ${_var} "" ) - else() - get_filename_component( __gccExeName "${__gccExePath}" NAME_WE ) - string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" ) - endif() - unset( __gccExePath ) - unset( __gccExePathsCount ) - unset( __gccExeName ) - else() - set( ${_var} "" ) - endif() -endmacro() - - -# fight against cygwin -set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools") -mark_as_advanced( ANDROID_FORBID_SYGWIN ) -if( ANDROID_FORBID_SYGWIN ) - if( CYGWIN ) - message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." ) - endif() - - if( CMAKE_HOST_WIN32 ) - # remove cygwin from PATH - set( __new_path "$ENV{PATH}") - __LIST_FILTER( __new_path "cygwin" ) - set(ENV{PATH} "${__new_path}") - unset(__new_path) - endif() -endif() - - -# detect current host platform -if( NOT DEFINED ANDROID_NDK_HOST_X64 AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64") - set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" ) - mark_as_advanced( ANDROID_NDK_HOST_X64 ) -endif() - -set( TOOL_OS_SUFFIX "" ) -if( CMAKE_HOST_APPLE ) - set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" ) - set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" ) -elseif( CMAKE_HOST_WIN32 ) - set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" ) - set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" ) - set( TOOL_OS_SUFFIX ".exe" ) -elseif( CMAKE_HOST_UNIX ) - set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" ) - set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" ) -else() - message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" ) -endif() - -if( NOT ANDROID_NDK_HOST_X64 ) - set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) -endif() - -# see if we have path to Android NDK -__INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK ) -if( NOT ANDROID_NDK ) - # see if we have path to Android standalone toolchain - __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN OBSOLETE_ANDROID_NDK_TOOLCHAIN_ROOT OBSOLETE_ENV_ANDROID_NDK_TOOLCHAIN_ROOT ) - - if( NOT ANDROID_STANDALONE_TOOLCHAIN ) - #try to find Android NDK in one of the the default locations - set( __ndkSearchPaths ) - foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} ) - foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} ) - list( APPEND __ndkSearchPaths "${__ndkSearchPath}${suffix}" ) - endforeach() - endforeach() - __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} ) - unset( __ndkSearchPaths ) - - if( ANDROID_NDK ) - message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" ) - message( STATUS " If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" ) - else() - #try to find Android standalone toolchain in one of the the default locations - __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) - - if( ANDROID_STANDALONE_TOOLCHAIN ) - message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" ) - message( STATUS " If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" ) - endif( ANDROID_STANDALONE_TOOLCHAIN ) - endif( ANDROID_NDK ) - endif( NOT ANDROID_STANDALONE_TOOLCHAIN ) -endif( NOT ANDROID_NDK ) - -# remember found paths -if( ANDROID_NDK ) - get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE ) - set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE ) - set( BUILD_WITH_ANDROID_NDK True ) - if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" ) - file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX r[0-9]+[a-z]? ) - string( REGEX MATCH r[0-9]+[a-z]? ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" ) - else() - set( ANDROID_NDK_RELEASE "r1x" ) - set( ANDROID_NDK_RELEASE_FULL "unreleased" ) - endif() -elseif( ANDROID_STANDALONE_TOOLCHAIN ) - get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE ) - # try to detect change - if( CMAKE_AR ) - string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length ) - string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath ) - if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN ) - message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." ) - endif() - unset( __androidStandaloneToolchainPreviousPath ) - unset( __length ) - endif() - set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" FORCE ) - set( BUILD_WITH_STANDALONE_TOOLCHAIN True ) -else() - list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH) - message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolchain. - You should either set an environment variable: - export ANDROID_NDK=~/my-android-ndk - or - export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain - or put the toolchain or NDK in the default path: - sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH} - sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" ) -endif() - -# android NDK layout -if( BUILD_WITH_ANDROID_NDK ) - if( NOT DEFINED ANDROID_NDK_LAYOUT ) - # try to automatically detect the layout - if( EXISTS "${ANDROID_NDK}/RELEASE.TXT") - set( ANDROID_NDK_LAYOUT "RELEASE" ) - elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" ) - set( ANDROID_NDK_LAYOUT "LINARO" ) - elseif( EXISTS "${ANDROID_NDK}/../../gcc/" ) - set( ANDROID_NDK_LAYOUT "ANDROID" ) - endif() - endif() - set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" ) - mark_as_advanced( ANDROID_NDK_LAYOUT ) - if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" ) - set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment - set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" ) - set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) - set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) - elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" ) - set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment - set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" ) - set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) - set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) - else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE" - set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" ) - set( ANDROID_NDK_TOOLCHAINS_SUBPATH "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" ) - set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" ) - endif() - get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE ) - - # try to detect change of NDK - if( CMAKE_AR ) - string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length ) - string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath ) - if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH ) - message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first. - " ) - endif() - unset( __androidNdkPreviousPath ) - unset( __length ) - endif() -endif() - - -# get all the details about standalone toolchain -if( BUILD_WITH_STANDALONE_TOOLCHAIN ) - __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" ) - set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) - set( __availableToolchains "standalone" ) - __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" ) - if( NOT __availableToolchainMachines ) - message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." ) - endif() - if( __availableToolchainMachines MATCHES i686 ) - set( __availableToolchainArchs "x86" ) - elseif( __availableToolchainMachines MATCHES arm ) - set( __availableToolchainArchs "arm" ) - elseif( __availableToolchainMachines MATCHES mipsel ) - set( __availableToolchainArchs "mipsel" ) - endif() - execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" -dumpversion - OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE ) - string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" ) - if( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/bin/clang${TOOL_OS_SUFFIX}" ) - list( APPEND __availableToolchains "standalone-clang" ) - list( APPEND __availableToolchainMachines ${__availableToolchainMachines} ) - list( APPEND __availableToolchainArchs ${__availableToolchainArchs} ) - list( APPEND __availableToolchainCompilerVersions ${__availableToolchainCompilerVersions} ) - endif() -endif() - -macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath ) - foreach( __toolchain ${${__availableToolchainsLst}} ) - if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" ) - string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" ) - else() - set( __gcc_toolchain "${__toolchain}" ) - endif() - __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" ) - if( __machine ) - string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" ) - if( __machine MATCHES i686 ) - set( __arch "x86" ) - elseif( __machine MATCHES arm ) - set( __arch "arm" ) - elseif( __machine MATCHES mipsel ) - set( __arch "mipsel" ) - endif() - list( APPEND __availableToolchainMachines "${__machine}" ) - list( APPEND __availableToolchainArchs "${__arch}" ) - list( APPEND __availableToolchainCompilerVersions "${__version}" ) - list( APPEND ${__availableToolchainsVar} "${__toolchain}" ) - endif() - unset( __gcc_toolchain ) - endforeach() -endmacro() - -# get all the details about NDK -if( BUILD_WITH_ANDROID_NDK ) - file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" ) - string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" ) - set( __availableToolchains "" ) - set( __availableToolchainMachines "" ) - set( __availableToolchainArchs "" ) - set( __availableToolchainCompilerVersions "" ) - if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" ) - # do not go through all toolchains if we know the name - set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" ) - __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) - if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) - __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) - if( __availableToolchains ) - set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) - endif() - endif() - endif() - if( NOT __availableToolchains ) - file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" ) - if( __availableToolchains ) - list(SORT __availableToolchainsLst) # we need clang to go after gcc - endif() - __LIST_FILTER( __availableToolchainsLst "^[.]" ) - __LIST_FILTER( __availableToolchainsLst "llvm" ) - __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) - if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) - __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) - if( __availableToolchains ) - set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) - endif() - endif() - endif() - if( NOT __availableToolchains ) - message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." ) - endif() -endif() - -# build list of available ABIs -set( ANDROID_SUPPORTED_ABIS "" ) -set( __uniqToolchainArchNames ${__availableToolchainArchs} ) -list( REMOVE_DUPLICATES __uniqToolchainArchNames ) -list( SORT __uniqToolchainArchNames ) -foreach( __arch ${__uniqToolchainArchNames} ) - list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} ) -endforeach() -unset( __uniqToolchainArchNames ) -if( NOT ANDROID_SUPPORTED_ABIS ) - message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." ) -endif() - -# choose target ABI -__INIT_VARIABLE( ANDROID_ABI OBSOLETE_ARM_TARGET OBSOLETE_ARM_TARGETS VALUES ${ANDROID_SUPPORTED_ABIS} ) -# verify that target ABI is supported -list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx ) -if( __androidAbiIdx EQUAL -1 ) - string( REPLACE ";" "\", \"", PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" ) - message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain. - Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\" - " ) -endif() -unset( __androidAbiIdx ) - -# set target ABI options -if( ANDROID_ABI STREQUAL "x86" ) - set( X86 true ) - set( ANDROID_NDK_ABI_NAME "x86" ) - set( ANDROID_ARCH_NAME "x86" ) - set( ANDROID_ARCH_FULLNAME "x86" ) - set( ANDROID_LLVM_TRIPLE "i686-none-linux-android" ) - set( CMAKE_SYSTEM_PROCESSOR "i686" ) -elseif( ANDROID_ABI STREQUAL "mips" ) - set( MIPS true ) - set( ANDROID_NDK_ABI_NAME "mips" ) - set( ANDROID_ARCH_NAME "mips" ) - set( ANDROID_ARCH_FULLNAME "mipsel" ) - set( ANDROID_LLVM_TRIPLE "mipsel-none-linux-android" ) - set( CMAKE_SYSTEM_PROCESSOR "mips" ) -elseif( ANDROID_ABI STREQUAL "armeabi" ) - set( ARMEABI true ) - set( ANDROID_NDK_ABI_NAME "armeabi" ) - set( ANDROID_ARCH_NAME "arm" ) - set( ANDROID_ARCH_FULLNAME "arm" ) - set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) - set( CMAKE_SYSTEM_PROCESSOR "armv5te" ) -elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" ) - set( ARMEABI_V6 true ) - set( ANDROID_NDK_ABI_NAME "armeabi" ) - set( ANDROID_ARCH_NAME "arm" ) - set( ANDROID_ARCH_FULLNAME "arm" ) - set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) - set( CMAKE_SYSTEM_PROCESSOR "armv6" ) - # need always fallback to older platform - set( ARMEABI true ) -elseif( ANDROID_ABI STREQUAL "armeabi-v7a") - set( ARMEABI_V7A true ) - set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) - set( ANDROID_ARCH_NAME "arm" ) - set( ANDROID_ARCH_FULLNAME "arm" ) - set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) - set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) -elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" ) - set( ARMEABI_V7A true ) - set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) - set( ANDROID_ARCH_NAME "arm" ) - set( ANDROID_ARCH_FULLNAME "arm" ) - set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) - set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) - set( VFPV3 true ) -elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" ) - set( ARMEABI_V7A true ) - set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) - set( ANDROID_ARCH_NAME "arm" ) - set( ANDROID_ARCH_FULLNAME "arm" ) - set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) - set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) - set( VFPV3 true ) - set( NEON true ) -else() - message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." ) -endif() - -if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" ) - # really dirty hack - # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run... - file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" ) -endif() - -if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 ) - __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD OBSOLETE_FORCE_ARM VALUES OFF ) - set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE ) - mark_as_advanced( ANDROID_FORCE_ARM_BUILD ) -else() - unset( ANDROID_FORCE_ARM_BUILD CACHE ) -endif() - -# choose toolchain -if( ANDROID_TOOLCHAIN_NAME ) - list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx ) - if( __toolchainIdx EQUAL -1 ) - list( SORT __availableToolchains ) - string( REPLACE ";" "\n * " toolchains_list "${__availableToolchains}" ) - set( toolchains_list " * ${toolchains_list}") - message( FATAL_ERROR "Specified toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing in your NDK or broken. Please verify that your NDK is working or select another compiler toolchain. -To configure the toolchain set CMake variable ANDROID_TOOLCHAIN_NAME to one of the following values:\n${toolchains_list}\n" ) - endif() - list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch ) - if( NOT __toolchainArch STREQUAL ANDROID_ARCH_FULLNAME ) - message( SEND_ERROR "Selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." ) - endif() -else() - set( __toolchainIdx -1 ) - set( __applicableToolchains "" ) - set( __toolchainMaxVersion "0.0.0" ) - list( LENGTH __availableToolchains __availableToolchainsCount ) - math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" ) - foreach( __idx RANGE ${__availableToolchainsCount} ) - list( GET __availableToolchainArchs ${__idx} __toolchainArch ) - if( __toolchainArch STREQUAL ANDROID_ARCH_FULLNAME ) - list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion ) - string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}") - if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion ) - set( __toolchainMaxVersion "${__toolchainVersion}" ) - set( __toolchainIdx ${__idx} ) - endif() - endif() - endforeach() - unset( __availableToolchainsCount ) - unset( __toolchainMaxVersion ) - unset( __toolchainVersion ) -endif() -unset( __toolchainArch ) -if( __toolchainIdx EQUAL -1 ) - message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." ) -endif() -list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME ) -list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME ) -list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION ) - -unset( __toolchainIdx ) -unset( __availableToolchains ) -unset( __availableToolchainMachines ) -unset( __availableToolchainArchs ) -unset( __availableToolchainCompilerVersions ) - -# choose native API level -__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL ) -string( REGEX MATCH "[0-9]+" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" ) -# adjust API level -set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} ) -foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) - if( NOT __level GREATER ANDROID_NATIVE_API_LEVEL AND NOT __level LESS __real_api_level ) - set( __real_api_level ${__level} ) - endif() -endforeach() -if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL EQUAL __real_api_level ) - message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'") - set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} ) -endif() -unset(__real_api_level) -# validate -list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx ) -if( __levelIdx EQUAL -1 ) - message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." ) -else() - if( BUILD_WITH_ANDROID_NDK ) - __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" ) - if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL ) - message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." ) - endif() - unset( __realApiLevel ) - endif() - set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE ) - if( CMAKE_VERSION VERSION_GREATER "2.8" ) - list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS ) - set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) - endif() -endif() -unset( __levelIdx ) - - -# remember target ABI -set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE ) -if( CMAKE_VERSION VERSION_GREATER "2.8" ) - list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME} ) - set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_FULLNAME}} ) -endif() - - -# runtime choice (STL, rtti, exceptions) -if( NOT ANDROID_STL ) - # honor legacy ANDROID_USE_STLPORT - if( DEFINED ANDROID_USE_STLPORT ) - if( ANDROID_USE_STLPORT ) - set( ANDROID_STL stlport_static ) - endif() - message( WARNING "You are using an obsolete variable ANDROID_USE_STLPORT to select the STL variant. Use -DANDROID_STL=stlport_static instead." ) - endif() - if( NOT ANDROID_STL ) - set( ANDROID_STL gnustl_static ) - endif() -endif() -set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" ) -set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" ) -mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES ) - -if( BUILD_WITH_ANDROID_NDK ) - if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared)$") - message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". -The possible values are: - none -> Do not configure the runtime. - system -> Use the default minimal system C++ runtime library. - system_re -> Same as system but with rtti and exceptions. - gabi++_static -> Use the GAbi++ runtime as a static library. - gabi++_shared -> Use the GAbi++ runtime as a shared library. - stlport_static -> Use the STLport runtime as a static library. - stlport_shared -> Use the STLport runtime as a shared library. - gnustl_static -> (default) Use the GNU STL as a static library. - gnustl_shared -> Use the GNU STL as a shared library. -" ) - endif() -elseif( BUILD_WITH_STANDALONE_TOOLCHAIN ) - if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared)$") - message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". -The possible values are: - none -> Do not configure the runtime. - gnustl_static -> (default) Use the GNU STL as a static library. - gnustl_shared -> Use the GNU STL as a shared library. -" ) - endif() -endif() - -unset( ANDROID_RTTI ) -unset( ANDROID_EXCEPTIONS ) -unset( ANDROID_STL_INCLUDE_DIRS ) -unset( __libstl ) -unset( __libsupcxx ) - -if( NOT _CMAKE_IN_TRY_COMPILE AND ANDROID_NDK_RELEASE STREQUAL "r7b" AND ARMEABI_V7A AND NOT VFPV3 AND ANDROID_STL MATCHES "gnustl" ) - message( WARNING "The GNU STL armeabi-v7a binaries from NDK r7b can crash non-NEON devices. The files provided with NDK r7b were not configured properly, resulting in crashes on Tegra2-based devices and others when trying to use certain floating-point functions (e.g., cosf, sinf, expf). -You are strongly recommended to switch to another NDK release. -" ) -endif() - -if( NOT _CMAKE_IN_TRY_COMPILE AND X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" ) - message( WARNING "The x86 system header file from NDK r6 has incorrect definition for ptrdiff_t. You are recommended to upgrade to a newer NDK release or manually patch the header: -See https://android.googlesource.com/platform/development.git f907f4f9d4e56ccc8093df6fee54454b8bcab6c2 - diff --git a/ndk/platforms/android-9/arch-x86/include/machine/_types.h b/ndk/platforms/android-9/arch-x86/include/machine/_types.h - index 5e28c64..65892a1 100644 - --- a/ndk/platforms/android-9/arch-x86/include/machine/_types.h - +++ b/ndk/platforms/android-9/arch-x86/include/machine/_types.h - @@ -51,7 +51,11 @@ typedef long int ssize_t; - #endif - #ifndef _PTRDIFF_T - #define _PTRDIFF_T - -typedef long ptrdiff_t; - +# ifdef __ANDROID__ - + typedef int ptrdiff_t; - +# else - + typedef long ptrdiff_t; - +# endif - #endif -" ) -endif() - - -# setup paths and STL for standalone toolchain -if( BUILD_WITH_STANDALONE_TOOLCHAIN ) - set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) - set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) - set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" ) - - if( NOT ANDROID_STL STREQUAL "none" ) - set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" ) - if( ARMEABI_V7A AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" ) - list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" ) - elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" ) - list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" ) - else() - list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" ) - endif() - # always search static GNU STL to get the location of libsupc++.a - if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" ) - set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb" ) - elseif( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" ) - set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}" ) - elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libstdc++.a" ) - set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb" ) - elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libstdc++.a" ) - set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" ) - endif() - if( __libstl ) - set( __libsupcxx "${__libstl}/libsupc++.a" ) - set( __libstl "${__libstl}/libstdc++.a" ) - endif() - if( NOT EXISTS "${__libsupcxx}" ) - message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain. - Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c. - You need to either upgrade to newer NDK or manually copy - $ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a - to - ${__libsupcxx} - " ) - endif() - if( ANDROID_STL STREQUAL "gnustl_shared" ) - if( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) - set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) - elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) - set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) - elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) - set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) - endif() - endif() - endif() -endif() - -# clang -if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" ) - set( ANDROID_COMPILER_IS_CLANG 1 ) - execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ) - string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}") -elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" ) - string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}") - string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-4.6" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) - if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" ) - message( FATAL_ERROR "Could not find the Clang compiler driver" ) - endif() - set( ANDROID_COMPILER_IS_CLANG 1 ) - set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) -else() - set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) - unset( ANDROID_COMPILER_IS_CLANG CACHE ) -endif() - -string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" ) -if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" ) - set( _clang_name "clang" ) -endif() - - -# setup paths and STL for NDK -if( BUILD_WITH_ANDROID_NDK ) - set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) - set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" ) - - if( ANDROID_STL STREQUAL "none" ) - # do nothing - elseif( ANDROID_STL STREQUAL "system" ) - set( ANDROID_RTTI OFF ) - set( ANDROID_EXCEPTIONS OFF ) - set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) - elseif( ANDROID_STL STREQUAL "system_re" ) - set( ANDROID_RTTI ON ) - set( ANDROID_EXCEPTIONS ON ) - set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) - elseif( ANDROID_STL MATCHES "gabi" ) - if( ANDROID_NDK_RELEASE STRLESS "r7" ) - message( FATAL_ERROR "gabi++ is not awailable in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.") - endif() - set( ANDROID_RTTI ON ) - set( ANDROID_EXCEPTIONS OFF ) - set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" ) - set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" ) - elseif( ANDROID_STL MATCHES "stlport" ) - if( NOT ANDROID_NDK_RELEASE STRLESS "r8d" ) - set( ANDROID_EXCEPTIONS ON ) - else() - set( ANDROID_EXCEPTIONS OFF ) - endif() - if( ANDROID_NDK_RELEASE STRLESS "r7" ) - set( ANDROID_RTTI OFF ) - else() - set( ANDROID_RTTI ON ) - endif() - set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" ) - set( __libstl "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" ) - elseif( ANDROID_STL MATCHES "gnustl" ) - set( ANDROID_EXCEPTIONS ON ) - set( ANDROID_RTTI ON ) - if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) - if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" ) - # gnustl binary for 4.7 compiler is buggy :( - # TODO: look for right fix - set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" ) - else() - set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) - endif() - else() - set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" ) - endif() - set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" ) - if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) - set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) - else() - set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" ) - endif() - else() - message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" ) - endif() - # find libsupc++.a - rtti & exceptions - if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" ) - set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer - if( NOT EXISTS "${__libsupcxx}" ) - set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8 - endif() - if( NOT EXISTS "${__libsupcxx}" ) # before r7 - if( ARMEABI_V7A ) - if( ANDROID_FORCE_ARM_BUILD ) - set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" ) - else() - set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" ) - endif() - elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD ) - set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" ) - else() - set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" ) - endif() - endif() - if( NOT EXISTS "${__libsupcxx}") - message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.") - endif() - endif() -endif() - - -# case of shared STL linkage -if( ANDROID_STL MATCHES "shared" AND DEFINED __libstl ) - string( REPLACE "_static.a" "_shared.so" __libstl "${__libstl}" ) - if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" ) - get_filename_component( __libstlname "${__libstl}" NAME ) - execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess ) - if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}") - message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" ) - endif() - unset( __fileCopyProcess ) - unset( __libstlname ) - endif() -endif() - - -# ccache support -__INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE ) -if( _ndk_ccache ) - if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE ) - unset( NDK_CCACHE CACHE ) - endif() - find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary") -else() - unset( NDK_CCACHE CACHE ) -endif() -unset( _ndk_ccache ) - - -# setup the cross-compiler -if( NOT CMAKE_C_COMPILER ) - if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) - set( CMAKE_C_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" ) - set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" ) - if( ANDROID_COMPILER_IS_CLANG ) - set( CMAKE_C_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") - set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") - else() - set( CMAKE_C_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") - set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") - endif() - else() - if( ANDROID_COMPILER_IS_CLANG ) - set( CMAKE_C_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") - set( CMAKE_CXX_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") - else() - set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler" ) - set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler" ) - endif() - endif() - set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "assembler" ) - set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" ) - set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) - set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" ) - set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" ) - set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" ) - set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" ) - set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" ) -endif() - -set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" ) -if( CMAKE_VERSION VERSION_LESS 2.8.5 ) - set( CMAKE_ASM_COMPILER_ARG1 "-c" ) -endif() -if( APPLE ) - find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool ) - if( NOT CMAKE_INSTALL_NAME_TOOL ) - message( FATAL_ERROR "Could not find install_name_tool, please check your installation." ) - endif() - mark_as_advanced( CMAKE_INSTALL_NAME_TOOL ) -endif() - -# Force set compilers because standard identification works badly for us -include( CMakeForceCompiler ) -CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU ) -if( ANDROID_COMPILER_IS_CLANG ) - set( CMAKE_C_COMPILER_ID Clang) -endif() -set( CMAKE_C_PLATFORM_ID Linux ) -set( CMAKE_C_SIZEOF_DATA_PTR 4 ) -set( CMAKE_C_HAS_ISYSROOT 1 ) -set( CMAKE_C_COMPILER_ABI ELF ) -CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU ) -if( ANDROID_COMPILER_IS_CLANG ) - set( CMAKE_CXX_COMPILER_ID Clang) -endif() -set( CMAKE_CXX_PLATFORM_ID Linux ) -set( CMAKE_CXX_SIZEOF_DATA_PTR 4 ) -set( CMAKE_CXX_HAS_ISYSROOT 1 ) -set( CMAKE_CXX_COMPILER_ABI ELF ) -set( CMAKE_CXX_SOURCE_FILE_EXTENSIONS cc cp cxx cpp CPP c++ C ) -# force ASM compiler (required for CMake < 2.8.5) -set( CMAKE_ASM_COMPILER_ID_RUN TRUE ) -set( CMAKE_ASM_COMPILER_ID GNU ) -set( CMAKE_ASM_COMPILER_WORKS TRUE ) -set( CMAKE_ASM_COMPILER_FORCED TRUE ) -set( CMAKE_COMPILER_IS_GNUASM 1) -set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm ) - -# flags and definitions -remove_definitions( -DANDROID ) -add_definitions( -DANDROID ) - -if( ANDROID_SYSROOT MATCHES "[ ;\"]" ) - if( CMAKE_HOST_WIN32 ) - # try to convert path to 8.3 form - file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" ) - execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}" - OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE - RESULT_VARIABLE __result ERROR_QUIET ) - if( __result EQUAL 0 ) - file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT ) - set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) - else() - set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" ) - endif() - else() - set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" ) - endif() - if( NOT _CMAKE_IN_TRY_COMPILE ) - # quotes can break try_compile and compiler identification - message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n") - endif() -else() - set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) -endif() - -# NDK flags -if( ARMEABI OR ARMEABI_V7A ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fpic -funwind-tables" ) - if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 ) - set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" ) - set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) - if( NOT ANDROID_COMPILER_IS_CLANG ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" ) - endif() - else() - # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI - set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" ) - set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) - if( NOT ANDROID_COMPILER_IS_CLANG ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) - endif() - endif() -elseif( X86 ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) - if( NOT ANDROID_COMPILER_IS_CLANG ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) - else() - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fPIC" ) - endif() - set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) - set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) -elseif( MIPS ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fpic -fno-strict-aliasing -finline-functions -ffunction-sections -funwind-tables -fmessage-length=0" ) - set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" ) - set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer" ) - if( NOT ANDROID_COMPILER_IS_CLANG ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" ) - set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) - endif() -elseif() - set( ANDROID_CXX_FLAGS_RELEASE "" ) - set( ANDROID_CXX_FLAGS_DEBUG "" ) -endif() - -set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries - -if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG ) - set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" ) -endif() - -if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/ -endif() - -# ABI-specific flags -if( ARMEABI_V7A ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" ) - if( NEON ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" ) - elseif( VFPV3 ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" ) - else() - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" ) - endif() -elseif( ARMEABI_V6 ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) # vfp == vfpv2 -elseif( ARMEABI ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" ) -endif() - -if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") ) - set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) - set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) - set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) -else() - set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) - set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) - set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) -endif() - -# STL -if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" ) - if( EXISTS "${__libstl}" ) - set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" ) - set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" ) - set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libstl}\"" ) - endif() - if( EXISTS "${__libsupcxx}" ) - set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) - set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) - set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) - # C objects: - set( CMAKE_C_CREATE_SHARED_LIBRARY " -o " ) - set( CMAKE_C_CREATE_SHARED_MODULE " -o " ) - set( CMAKE_C_LINK_EXECUTABLE " -o " ) - set( CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) - set( CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_C_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) - set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) - endif() - if( ANDROID_STL MATCHES "gnustl" ) - if( NOT EXISTS "${ANDROID_LIBM_PATH}" ) - set( ANDROID_LIBM_PATH -lm ) - endif() - set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" ) - set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" ) - set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" ) - endif() -endif() - -# variables controlling optional build flags -if (ANDROID_NDK_RELEASE STRLESS "r7") - # libGLESv2.so in NDK's prior to r7 refers to missing external symbols. - # So this flag option is required for all projects using OpenGL from native. - __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES ON ) -else() - __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF ) -endif() -__INIT_VARIABLE( ANDROID_NO_UNDEFINED OBSOLETE_NO_UNDEFINED VALUES ON ) -__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON ) -__INIT_VARIABLE( ANDROID_GOLD_LINKER VALUES ON ) -__INIT_VARIABLE( ANDROID_NOEXECSTACK VALUES ON ) -__INIT_VARIABLE( ANDROID_RELRO VALUES ON ) - -set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" ) -set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) -set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) -set( ANDROID_GOLD_LINKER ${ANDROID_GOLD_LINKER} CACHE BOOL "Enables gold linker (only avaialble for NDK r8b for ARM and x86 architectures on linux-86 and darwin-x86 hosts)" ) -set( ANDROID_NOEXECSTACK ${ANDROID_NOEXECSTACK} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) -set( ANDROID_RELRO ${ANDROID_RELRO} CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" ) -mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO ) - -# linker flags -set( ANDROID_LINKER_FLAGS "" ) - -if( ARMEABI_V7A ) - # this is *required* to use the following linker flags that routes around - # a CPU bug in some Cortex-A8 implementations: - set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--fix-cortex-a8" ) -endif() - -if( ANDROID_NO_UNDEFINED ) - if( MIPS ) - # there is some sysroot-related problem in mips linker... - if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) - set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" ) - endif() - else() - set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" ) - endif() -endif() - -if( ANDROID_SO_UNDEFINED ) - set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" ) -endif() - -if( ANDROID_FUNCTION_LEVEL_LINKING ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" ) - set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" ) -endif() - -if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" ) - if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE STRGREATER "r8b") AND (ARMEABI OR ARMEABI_V7A OR X86) ) - set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" ) - elseif( ANDROID_NDK_RELEASE STRGREATER "r8b") - set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" ) - elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE ) - message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342 - On Linux and OS X host platform you can workaround this problem using gold linker (default). - Rerun cmake with -DANDROID_GOLD_LINKER=ON option in case of problems. -" ) - endif() -endif() # version 4.6 - -if( ANDROID_NOEXECSTACK ) - if( ANDROID_COMPILER_IS_CLANG ) - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Xclang -mnoexecstack" ) - else() - set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Wa,--noexecstack" ) - endif() - set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,noexecstack" ) -endif() - -if( ANDROID_RELRO ) - set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now" ) -endif() - -if( ANDROID_COMPILER_IS_CLANG ) - set( ANDROID_CXX_FLAGS "-Qunused-arguments ${ANDROID_CXX_FLAGS}" ) - if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD ) - set( ANDROID_CXX_FLAGS_RELEASE "-target thumbv7-none-linux-androideabi ${ANDROID_CXX_FLAGS_RELEASE}" ) - set( ANDROID_CXX_FLAGS_DEBUG "-target ${ANDROID_LLVM_TRIPLE} ${ANDROID_CXX_FLAGS_DEBUG}" ) - else() - set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} ${ANDROID_CXX_FLAGS}" ) - endif() - if( BUILD_WITH_ANDROID_NDK ) - set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" ) - endif() -endif() - -# cache flags -set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" ) -set( CMAKE_C_FLAGS "" CACHE STRING "c flags" ) -set( CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c++ Release flags" ) -set( CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c Release flags" ) -set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" ) -set( CMAKE_C_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" ) -set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags" ) -set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags" ) -set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags" ) - -# put flags to cache (for debug purpose only) -set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Android specific c/c++ flags" ) -set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" ) -set( ANDROID_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG}" CACHE INTERNAL "Android specific c/c++ Debug flags" ) -set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Android specific c/c++ linker flags" ) - -# finish flags -set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" ) -set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" ) -set( CMAKE_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" ) -set( CMAKE_C_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" ) -set( CMAKE_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" ) -set( CMAKE_C_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" ) -set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) -set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) -set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) - -if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" ) - set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" ) - set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" ) - set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" ) -endif() - -# configure rtti -if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES ) - if( ANDROID_RTTI ) - set( CMAKE_CXX_FLAGS "-frtti ${CMAKE_CXX_FLAGS}" ) - else() - set( CMAKE_CXX_FLAGS "-fno-rtti ${CMAKE_CXX_FLAGS}" ) - endif() -endif() - -# configure exceptios -if( DEFINED ANDROID_EXCEPTIONS AND ANDROID_STL_FORCE_FEATURES ) - if( ANDROID_EXCEPTIONS ) - set( CMAKE_CXX_FLAGS "-fexceptions ${CMAKE_CXX_FLAGS}" ) - set( CMAKE_C_FLAGS "-fexceptions ${CMAKE_C_FLAGS}" ) - else() - set( CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}" ) - set( CMAKE_C_FLAGS "-fno-exceptions ${CMAKE_C_FLAGS}" ) - endif() -endif() - -# global includes and link directories -include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLUDE_DIRS} ) -link_directories( "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ) - -# detect if need link crtbegin_so.o explicitly -if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK ) - set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" ) - string( REPLACE "" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" ) - string( REPLACE "" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" __cmd "${__cmd}" ) - string( REPLACE "" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" ) - string( REPLACE "" "" __cmd "${__cmd}" ) - string( REPLACE "" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" ) - string( REPLACE "" "-shared" __cmd "${__cmd}" ) - string( REPLACE "" "" __cmd "${__cmd}" ) - string( REPLACE "" "" __cmd "${__cmd}" ) - string( REPLACE "" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" ) - string( REPLACE "" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" ) - string( REPLACE "" "" __cmd "${__cmd}" ) - separate_arguments( __cmd ) - foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN ) - if( ${__var} ) - set( __tmp "${${__var}}" ) - separate_arguments( __tmp ) - string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}") - endif() - endforeach() - string( REPLACE "'" "" __cmd "${__cmd}" ) - string( REPLACE "\"" "" __cmd "${__cmd}" ) - execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET ) - if( __cmd_result EQUAL 0 ) - set( ANDROID_EXPLICIT_CRT_LINK ON ) - else() - set( ANDROID_EXPLICIT_CRT_LINK OFF ) - endif() -endif() - -if( ANDROID_EXPLICIT_CRT_LINK ) - set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) - set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) -endif() - -# setup output directories -set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" ) -set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" ) - -if(NOT _CMAKE_IN_TRY_COMPILE) - if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" ) - set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" ) - else() - set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" ) - endif() - set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "path for android libs" ) -endif() - -# set these global flags for cmake client scripts to change behavior -set( ANDROID True ) -set( BUILD_ANDROID True ) - -# where is the target environment -set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" ) - -# only search for libraries and includes in the ndk toolchain -set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) -set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) -set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) - - -# macro to find packages on the host OS -macro( find_host_package ) - set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) - set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) - set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) - if( CMAKE_HOST_WIN32 ) - SET( WIN32 1 ) - SET( UNIX ) - elseif( CMAKE_HOST_APPLE ) - SET( APPLE 1 ) - SET( UNIX ) - endif() - find_package( ${ARGN} ) - SET( WIN32 ) - SET( APPLE ) - SET( UNIX 1 ) - set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) - set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) - set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) -endmacro() - - -# macro to find programs on the host OS -macro( find_host_program ) - set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) - set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) - set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) - if( CMAKE_HOST_WIN32 ) - SET( WIN32 1 ) - SET( UNIX ) - elseif( CMAKE_HOST_APPLE ) - SET( APPLE 1 ) - SET( UNIX ) - endif() - find_program( ${ARGN} ) - SET( WIN32 ) - SET( APPLE ) - SET( UNIX 1 ) - set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) - set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) - set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) -endmacro() - - -macro( ANDROID_GET_ABI_RAWNAME TOOLCHAIN_FLAG VAR ) - if( "${TOOLCHAIN_FLAG}" STREQUAL "ARMEABI" ) - set( ${VAR} "armeabi" ) - elseif( "${TOOLCHAIN_FLAG}" STREQUAL "ARMEABI_V7A" ) - set( ${VAR} "armeabi-v7a" ) - elseif( "${TOOLCHAIN_FLAG}" STREQUAL "X86" ) - set( ${VAR} "x86" ) - elseif( "${TOOLCHAIN_FLAG}" STREQUAL "MIPS" ) - set( ${VAR} "mips" ) - else() - set( ${VAR} "unknown" ) - endif() -endmacro() - - -# export toolchain settings for the try_compile() command -if( NOT PROJECT_NAME STREQUAL "CMAKE_TRY_COMPILE" ) - set( __toolchain_config "") - foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN ANDROID_SET_OBSOLETE_VARIABLES - ANDROID_NDK_HOST_X64 - ANDROID_NDK - ANDROID_NDK_LAYOUT - ANDROID_STANDALONE_TOOLCHAIN - ANDROID_TOOLCHAIN_NAME - ANDROID_ABI - ANDROID_NATIVE_API_LEVEL - ANDROID_STL - ANDROID_STL_FORCE_FEATURES - ANDROID_FORCE_ARM_BUILD - ANDROID_NO_UNDEFINED - ANDROID_SO_UNDEFINED - ANDROID_FUNCTION_LEVEL_LINKING - ANDROID_GOLD_LINKER - ANDROID_NOEXECSTACK - ANDROID_RELRO - ANDROID_LIBM_PATH - ANDROID_EXPLICIT_CRT_LINK - ) - if( DEFINED ${__var} ) - if( "${__var}" MATCHES " ") - set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" ) - else() - set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" ) - endif() - endif() - endforeach() - file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" ) - unset( __toolchain_config ) -endif() - - -# set some obsolete variables for backward compatibility -set( ANDROID_SET_OBSOLETE_VARIABLES ON CACHE BOOL "Define obsolete Andrid-specific cmake variables" ) -mark_as_advanced( ANDROID_SET_OBSOLETE_VARIABLES ) -if( ANDROID_SET_OBSOLETE_VARIABLES ) - set( ANDROID_API_LEVEL ${ANDROID_NATIVE_API_LEVEL} ) - set( ARM_TARGET "${ANDROID_ABI}" ) - set( ARMEABI_NDK_NAME "${ANDROID_NDK_ABI_NAME}" ) -endif() - - -# Variables controlling behavior or set by cmake toolchain: -# ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips" -# ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14 (depends on NDK version) -# ANDROID_STL : gnustl_static/gnustl_shared/stlport_static/stlport_shared/gabi++_static/gabi++_shared/system_re/system/none -# ANDROID_FORBID_SYGWIN : ON/OFF -# ANDROID_NO_UNDEFINED : ON/OFF -# ANDROID_SO_UNDEFINED : OFF/ON (default depends on NDK version) -# ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF -# ANDROID_GOLD_LINKER : ON/OFF -# ANDROID_NOEXECSTACK : ON/OFF -# ANDROID_RELRO : ON/OFF -# ANDROID_FORCE_ARM_BUILD : ON/OFF -# ANDROID_STL_FORCE_FEATURES : ON/OFF -# ANDROID_SET_OBSOLETE_VARIABLES : ON/OFF -# Can be set only at the first run: -# ANDROID_NDK -# ANDROID_STANDALONE_TOOLCHAIN -# ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain -# ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems) -# ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID) -# LIBRARY_OUTPUT_PATH_ROOT : -# NDK_CCACHE : -# Obsolete: -# ANDROID_API_LEVEL : superseded by ANDROID_NATIVE_API_LEVEL -# ARM_TARGET : superseded by ANDROID_ABI -# ARM_TARGETS : superseded by ANDROID_ABI (can be set only) -# ANDROID_NDK_TOOLCHAIN_ROOT : superseded by ANDROID_STANDALONE_TOOLCHAIN (can be set only) -# ANDROID_USE_STLPORT : superseded by ANDROID_STL=stlport_static -# ANDROID_LEVEL : superseded by ANDROID_NATIVE_API_LEVEL (completely removed) -# -# Primary read-only variables: -# ANDROID : always TRUE -# ARMEABI : TRUE for arm v6 and older devices -# ARMEABI_V6 : TRUE for arm v6 -# ARMEABI_V7A : TRUE for arm v7a -# NEON : TRUE if NEON unit is enabled -# VFPV3 : TRUE if VFP version 3 is enabled -# X86 : TRUE if configured for x86 -# MIPS : TRUE if configured for mips -# BUILD_ANDROID : always TRUE -# BUILD_WITH_ANDROID_NDK : TRUE if NDK is used -# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used -# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform -# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86" or "mips" depending on ANDROID_ABI -# ANDROID_NDK_RELEASE : one of r5, r5b, r5c, r6, r6b, r7, r7b, r7c, r8, r8b, r8c, r8d, r8e; set only for NDK -# ANDROID_ARCH_NAME : "arm" or "x86" or "mips" depending on ANDROID_ABI -# ANDROID_SYSROOT : path to the compiler sysroot -# TOOL_OS_SUFFIX : "" or ".exe" depending on host platform -# ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used -# Obsolete: -# ARMEABI_NDK_NAME : superseded by ANDROID_NDK_ABI_NAME -# -# Secondary (less stable) read-only variables: -# ANDROID_COMPILER_VERSION : GCC version used -# ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform -# ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI -# ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux" -# ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK) -# ANDROID_CLANG_TOOLCHAIN_ROOT : path to clang tools -# ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK -# ANDROID_STL_INCLUDE_DIRS : stl include paths -# ANDROID_RTTI : if rtti is enabled by the runtime -# ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime -# ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used -# ANDROID_CLANG_VERSION : version of clang compiler if clang is used -# ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product//obj/lib/libm.so) to workaround unresolved `sincos` -# -# Defaults: -# ANDROID_DEFAULT_NDK_API_LEVEL -# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH} -# ANDROID_NDK_SEARCH_PATHS -# ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH -# ANDROID_SUPPORTED_ABIS_${ARCH} -# ANDROID_SUPPORTED_NDK_VERSIONS diff --git a/android/readme.txt b/android/readme.txt deleted file mode 100644 index 2d5f3962f..000000000 --- a/android/readme.txt +++ /dev/null @@ -1 +0,0 @@ -All Android specific sources are moved to platforms/android. \ No newline at end of file diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index ad0f0daad..f5ac42a01 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 f71cbeeaa..7a197db83 100644 --- a/apps/haartraining/CMakeLists.txt +++ b/apps/haartraining/CMakeLists.txt @@ -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 1c4bad52d..92fee8e84 100644 --- a/apps/haartraining/_cvcommon.h +++ b/apps/haartraining/_cvcommon.h @@ -90,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/performance.cpp b/apps/haartraining/performance.cpp index a95e4d4c4..cb8dda1c8 100644 --- a/apps/haartraining/performance.cpp +++ b/apps/haartraining/performance.cpp @@ -375,4 +375,3 @@ int main( int argc, char* argv[] ) return 0; } - diff --git a/apps/sft/CMakeLists.txt b/apps/sft/CMakeLists.txt index 8b950225c..05bd337c3 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 3cc64c7fe..9157575a1 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 4a0a03f36..5c142a749 100644 --- a/apps/sft/include/sft/common.hpp +++ b/apps/sft/include/sft/common.hpp @@ -71,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 3d39d3272..c6e85b264 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 98d619256..7504f4033 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 7b5138763..79d41032e 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 72e51b9ea..eb0c83df5 100644 --- a/apps/traincascade/CMakeLists.txt +++ b/apps/traincascade/CMakeLists.txt @@ -34,4 +34,3 @@ if(ENABLE_SOLUTION_FOLDERS) endif() install(TARGETS ${the_target} RUNTIME DESTINATION bin COMPONENT main) - diff --git a/apps/traincascade/boost.cpp b/apps/traincascade/boost.cpp index 29ac4bc9a..732704a4a 100644 --- a/apps/traincascade/boost.cpp +++ b/apps/traincascade/boost.cpp @@ -957,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; diff --git a/apps/traincascade/cascadeclassifier.cpp b/apps/traincascade/cascadeclassifier.cpp index 3983a614f..5c96b45f7 100644 --- a/apps/traincascade/cascadeclassifier.cpp +++ b/apps/traincascade/cascadeclassifier.cpp @@ -159,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; @@ -206,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) @@ -325,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 @@ -339,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 << "]"; @@ -350,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; @@ -371,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; @@ -453,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; @@ -499,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]; @@ -510,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; } @@ -531,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/traincascade.cpp b/apps/traincascade/traincascade.cpp index 7b8fcddd8..a896c216c 100644 --- a/apps/traincascade/traincascade.cpp +++ b/apps/traincascade/traincascade.cpp @@ -18,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 7ce4c49ae..000000000 --- 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 7514285d9..8a297c685 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 a71bcf06e..bfca6a0bc 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -233,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: @@ -294,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 300fcd419..000000000 --- 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 ee4188897..0173223d4 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) @@ -283,7 +283,7 @@ macro(add_android_project target path) ocv_include_modules_recurse(${android_proj_NATIVE_DEPS}) ocv_include_directories("${path}/jni") - if (NATIVE_APP_GLUE AND 0) + 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) diff --git a/cmake/OpenCVDetectCUDA.cmake b/cmake/OpenCVDetectCUDA.cmake index c44c8129e..076da108f 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() @@ -29,10 +24,42 @@ if(CUDA_FOUND) if(${CUDA_VERSION} VERSION_LESS "5.5") find_cuda_helper_libs(npp) else() - 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}) + # 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) @@ -67,7 +94,11 @@ 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/checks/OpenCVDetectCudaArch.cu" "--run" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/" @@ -81,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") diff --git a/cmake/OpenCVDetectOpenCL.cmake b/cmake/OpenCVDetectOpenCL.cmake index a1e8bbac7..c96df82e2 100644 --- a/cmake/OpenCVDetectOpenCL.cmake +++ b/cmake/OpenCVDetectOpenCL.cmake @@ -20,10 +20,24 @@ else(APPLE) DOC "OpenCL include directory" NO_DEFAULT_PATH) - 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) + 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() + set(OPENCL_POSSIBLE_LIB_SUFFIXES lib) endif() find_library(OPENCL_LIBRARY @@ -44,7 +58,7 @@ if(OPENCL_FOUND) set(OPENCL_INCLUDE_DIRS ${OPENCL_INCLUDE_DIR}) set(OPENCL_LIBRARIES ${OPENCL_LIBRARY}) - if(WIN64) + if(WIN32 AND X86_64) set(CLAMD_POSSIBLE_LIB_SUFFIXES lib64/import) elseif(WIN32) set(CLAMD_POSSIBLE_LIB_SUFFIXES lib32/import) diff --git a/cmake/OpenCVDetectPython.cmake b/cmake/OpenCVDetectPython.cmake index f27176d66..0ef0be9c9 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,39 +12,15 @@ if(WIN32 AND NOT PYTHON_EXECUTABLE) ) endforeach() endif() -find_host_package(PythonInterp 2.0) +find_host_package(PythonInterp "${MIN_VER_PYTHON}") 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) @@ -78,39 +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) - 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) - 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) -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/OpenCVFindIPP.cmake b/cmake/OpenCVFindIPP.cmake index d1af60565..772cae886 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 59ce1cd05..c80beca05 100644 --- a/cmake/OpenCVFindLibsGUI.cmake +++ b/cmake/OpenCVFindLibsGUI.cmake @@ -5,17 +5,16 @@ #--- Win32 UI --- ocv_clear_vars(HAVE_WIN32UI) if(WITH_WIN32UI) - TRY_COMPILE(HAVE_WIN32UI - "${OPENCV_BINARY_DIR}/CMakeFiles/CMakeTmp" + try_compile(HAVE_WIN32UI + "${OpenCV_BINARY_DIR}" "${OpenCV_SOURCE_DIR}/cmake/checks/win32uitest.cpp" - CMAKE_FLAGS "\"user32.lib\" \"gdi32.lib\"" - OUTPUT_VARIABLE OUTPUT) -endif(WITH_WIN32UI) + CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=user32;gdi32") +endif() # --- QT4 --- ocv_clear_vars(HAVE_QT HAVE_QT5) if(WITH_QT) - if(NOT CMAKE_VERSION VERSION_LESS 2.8.3 AND NOT WITH_QT EQUAL 4) + if(NOT WITH_QT EQUAL 4) find_package(Qt5Core) find_package(Qt5Gui) find_package(Qt5Widgets) @@ -24,7 +23,6 @@ if(WITH_QT) if(Qt5Core_FOUND AND Qt5Gui_FOUND AND Qt5Widgets_FOUND AND Qt5Test_FOUND AND Qt5Concurrent_FOUND) set(HAVE_QT5 ON) set(HAVE_QT ON) - add_definitions(-DHAVE_QT) find_package(Qt5OpenGL) if(Qt5OpenGL_FOUND) set(QT_QTOPENGL_FOUND ON) @@ -36,7 +34,6 @@ if(WITH_QT) find_package(Qt4 REQUIRED QtCore QtGui QtTest) 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 endif() endif() endif() @@ -61,10 +58,18 @@ if(WITH_OPENGL) 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 ed62c9362..d8ddcfeb7 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,56 +35,59 @@ 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) --- -if(WITH_JPEG AND NOT IOS) +if(WITH_JPEG) if(BUILD_JPEG) ocv_clear_vars(JPEG_FOUND) 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,53 +131,55 @@ 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) --- -if(WITH_PNG AND NOT IOS) +if(WITH_PNG) if(BUILD_PNG) ocv_clear_vars(PNG_FOUND) else() include(FindPNG) if(PNG_FOUND) include(CheckIncludeFile) - check_include_file("${PNG_PNG_INCLUDE_DIR}/png.h" HAVE_PNG_H) 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) @@ -183,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 db71b8aeb..b8945c257 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) diff --git a/cmake/OpenCVFindLibsVideo.cmake b/cmake/OpenCVFindLibsVideo.cmake index 96d480584..eba6fa988 100644 --- a/cmake/OpenCVFindLibsVideo.cmake +++ b/cmake/OpenCVFindLibsVideo.cmake @@ -3,13 +3,12 @@ # ---------------------------------------------------------------------------- ocv_clear_vars(HAVE_VFW) -if (WITH_VFW) - TRY_COMPILE(HAVE_VFW - "${OPENCV_BINARY_DIR}/CMakeFiles/CMakeTmp" +if(WITH_VFW) + try_compile(HAVE_VFW + "${OpenCV_BINARY_DIR}" "${OpenCV_SOURCE_DIR}/cmake/checks/vfwtest.cpp" - CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=vfw32" - OUTPUT_VARIABLE OUTPUT) - endif(WITH_VFW) + CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=vfw32") +endif(WITH_VFW) # --- GStreamer --- ocv_clear_vars(HAVE_GSTREAMER) @@ -87,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() @@ -257,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 7e439fd8d..000000000 --- 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 27e2a78ad..6b86b609e 100644 --- a/cmake/OpenCVFindXimea.cmake +++ b/cmake/OpenCVFindXimea.cmake @@ -19,7 +19,7 @@ set(XIMEA_LIBRARY_DIR) 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}) set(XIMEA_FOUND 1) # set LIB folders @@ -43,4 +43,4 @@ endif() mark_as_advanced(FORCE XIMEA_FOUND) mark_as_advanced(FORCE XIMEA_PATH) -mark_as_advanced(FORCE XIMEA_LIBRARY_DIR) \ No newline at end of file +mark_as_advanced(FORCE XIMEA_LIBRARY_DIR) diff --git a/cmake/OpenCVGenConfig.cmake b/cmake/OpenCVGenConfig.cmake index c99cae788..7ccf3ef42 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}}) diff --git a/cmake/OpenCVGenHeaders.cmake b/cmake/OpenCVGenHeaders.cmake index d2d38c90a..c7129fefa 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 000000000..97c674ceb --- /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 49d670734..7bfc7bc5a 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 e05ad4c48..000000000 --- a/cmake/OpenCVLegacyOptions.cmake +++ /dev/null @@ -1,25 +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) -ocv_legacy_option(WITH_VIDEOINPUT WITH_DSHOW) - -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 000000000..b659a8379 --- /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 00eb3cfa4..4956edf91 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: @@ -470,8 +471,16 @@ endmacro() # ocv_create_module() # ocv_create_module(SKIP_LINK) macro(ocv_create_module) + # 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") + "${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() @@ -511,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() @@ -572,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 @@ -639,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}) @@ -687,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}) @@ -712,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 9b3efd9d1..060965346 100644 --- a/cmake/OpenCVPCHSupport.cmake +++ b/cmake/OpenCVPCHSupport.cmake @@ -279,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 @@ -344,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 59366eb03..ddf029067 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) @@ -515,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 03de98068..c8ce40308 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/checks/OpenCVDetectCudaArch.cu b/cmake/checks/OpenCVDetectCudaArch.cu index 008f8ba8d..9d7086cf2 100644 --- a/cmake/checks/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 index 63d545788..8d8ecb271 100644 --- a/cmake/checks/vfwtest.cpp +++ b/cmake/checks/vfwtest.cpp @@ -7,4 +7,4 @@ int main() AVIFileInit(); AVIFileExit(); return 0; -} \ No newline at end of file +} diff --git a/cmake/checks/winrttest.cpp b/cmake/checks/winrttest.cpp new file mode 100644 index 000000000..9ec0c9ac1 --- /dev/null +++ b/cmake/checks/winrttest.cpp @@ -0,0 +1,6 @@ +#include + +int main(int, char**) +{ + return 0; +} diff --git a/cmake/cl2cpp.cmake b/cmake/cl2cpp.cmake index 4f18e9e64..1e932eabd 100644 --- a/cmake/cl2cpp.cmake +++ b/cmake/cl2cpp.cmake @@ -32,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 0b432a074..b5ac5f8e2 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 1dcd84030..90749488a 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 14e601019..0e63d705c 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 a419b0c3f..56c5d5aad 100644 --- a/cmake/templates/cvconfig.h.cmake +++ b/cmake/templates/cvconfig.h.cmake @@ -1,20 +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}" -/* Video for Windows support */ -#cmakedefine HAVE_VFW +/* 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 @@ -22,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 @@ -40,188 +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 - -/* Win32 UI */ -#cmakedefine HAVE_WIN32UI +#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}" - -/* 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 - -/* 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 - -/* DirectShow Video Capture library */ -#cmakedefine HAVE_DSHOW +/* V4L/V4L2 capturing support via libv4l */ +#cmakedefine HAVE_LIBV4L /* Microsoft Media Foundation Capture library */ #cmakedefine HAVE_MSMF -/* XIMEA camera support */ -#cmakedefine HAVE_XIMEA +/* NVidia Video Decoding API*/ +#cmakedefine HAVE_NVCUVID + +/* OpenCL Support */ +#cmakedefine HAVE_OPENCL + +/* 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 4f6415cab..5b94e4d6c 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 5d58e40e4..149871502 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 70f4809d2..888740bd4 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,7 +49,7 @@ 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() @@ -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 904ff361d..0a3099a8c 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 a376c9759..d0d43031c 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 49a57e9ec..4d410be8a 100644 --- a/doc/_themes/blue/static/default.css_t +++ b/doc/_themes/blue/static/default.css_t @@ -387,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 206193f6f..bc0b99b2a 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 c18bf0726..0290fc70f 100755 --- a/doc/check_docs.py +++ b/doc/check_docs.py @@ -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/conf.py b/doc/conf.py index f3f7aec58..2cbcdf886 100755 --- a/doc/conf.py +++ b/doc/conf.py @@ -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 @@ -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 e69de29bb..491c160cc 100644 --- a/doc/mymath.sty +++ b/doc/mymath.sty @@ -0,0 +1,42 @@ +\ProvidesPackage{mymath} + +\newcommand{\matTT}[9]{ +\[ +\left|\begin{array}{ccc} + #1 & #2 & #3\\ + #4 & #5 & #6\\ + #7 & #8 & #9 +\end{array}\right| +\] +} + +\newcommand{\fork}[4]{ + \left\{ + \begin{array}{l l} + #1 & \mbox{#2}\\ + #3 & \mbox{#4}\\ + \end{array} \right.} +\newcommand{\forkthree}[6]{ + \left\{ + \begin{array}{l l} + #1 & \mbox{#2}\\ + #3 & \mbox{#4}\\ + #5 & \mbox{#6}\\ + \end{array} \right.} + +\newcommand{\vecthree}[3]{ +\begin{bmatrix} + #1\\ + #2\\ + #3 +\end{bmatrix} +} + +\newcommand{\vecthreethree}[9]{ +\begin{bmatrix} + #1 & #2 & #3\\ + #4 & #5 & #6\\ + #7 & #8 & #9 +\end{bmatrix} +} + diff --git a/doc/opencv-logo2.png b/doc/opencv-logo2.png index 615fd2add..bc71a2ae5 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 e76bd016e..fc0c0fa41 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/pattern_tools/svgfig.py b/doc/pattern_tools/svgfig.py index 86afa5913..c690c9ff0 100755 --- a/doc/pattern_tools/svgfig.py +++ b/doc/pattern_tools/svgfig.py @@ -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/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 96% rename from doc/tutorials/contrib/retina_model/retina_model.rst rename to doc/tutorials/bioinspired/retina_model/retina_model.rst index 86e13e732..e8527ee8b 100644 --- a/doc/tutorials/contrib/retina_model/retina_model.rst +++ b/doc/tutorials/bioinspired/retina_model/retina_model.rst @@ -107,14 +107,16 @@ This retina filter code includes the research contributions of phd/research coll 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 @@ -128,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 @@ -229,20 +231,20 @@ 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; + cv::Ptr myRetina; // if the last parameter is 'log', then activate log sampling (favour foveal vision and subsamples peripheral vision) if (useLogSampling) { - myRetina = cv::createRetina(inputFrame.size(), true, cv::RETINA_COLOR_BAYER, true, 2.0, 10.0); + myRetina = cv::bioinspired::createRetina(inputFrame.size(), true, cv::bioinspired::RETINA_COLOR_BAYER, true, 2.0, 10.0); } else// -> else allocate "classical" retina : - myRetina = cv::createRetina(inputFrame.size()); + 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*. 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 000000000..50bdcbb62 --- /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 000000000..88869e98f --- /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 77723b2b8..2cf00f42a 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 4eff2640a..e08550750 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/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 87166b7cc..42f6a6091 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 99d669274..9285509b0 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 03d82bbd4..76c5a4541 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 b50d97635..4150265d1 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 829e27cac..a598a95dd 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 ded9e78fa..c2780c266 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 2d97f83be..b6e2dfa2b 100644 --- a/doc/tutorials/features2d/feature_description/feature_description.rst +++ b/doc/tutorials/features2d/feature_description/feature_description.rst @@ -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 1c9ca7cf8..02da6d080 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 4b3ffbcae..9839c8984 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; diff --git a/doc/tutorials/features2d/feature_homography/feature_homography.rst b/doc/tutorials/features2d/feature_homography/feature_homography.rst index 0d7822959..3040ed7d7 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 cc90082b8..f4107804b 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 a267b1380..4e9015cb6 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 465ff216c..d33bf3df6 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 9f71e987f..1495befc7 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 0f6bb33fa..e0e4ea47e 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 2a6d57ffb..6e127a98f 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 86400bfae..2e8fe9559 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 0ba7c323c..ef6eacce2 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 dabfa5e8c..5749123c1 100644 --- a/doc/tutorials/highgui/trackbar/trackbar.rst +++ b/doc/tutorials/highgui/trackbar/trackbar.rst @@ -152,8 +152,3 @@ Result .. image:: images/Adding_Trackbars_Tutorial_Result_1.jpg :alt: Adding Trackbars - Lena :align: center - - - - - diff --git a/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.rst b/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.rst index 133a613ad..9277a101d 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 d8a91560e..afe15ee0d 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 01c9050f2..ae2d0c8ac 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 ecd4ba219..96257683e 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 6b872bff5..d716c0832 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 a8b9fdf74..a060aa779 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 b60192978..d61b49337 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 6baa3a3d7..ca9d44546 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 00baae2ac..dacc5b93a 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 f91730ec8..24c276dc3 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 0986e1edc..9c7fbb85f 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 1fca7df93..68cf80dc7 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 c1ed79cea..eb5d19e3b 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 15ac2f51f..350ca38d4 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 b7f72c815..2d68cc247 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 1be239cfb..a371c02c8 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 b6c859dc3..78566e7d2 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.5-android-sdk + OpenCV-2.4.6-android-sdk |_ apk - | |_ OpenCV_2.4.5_binary_pack_armv7a.apk - | |_ OpenCV_2.4.5_Manager_2.7_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.5-android-sdk.zip + unzip ~/Downloads/OpenCV-2.4.6-android-sdk.zip -.. |opencv_android_bin_pack| replace:: :file:`OpenCV-2.4.5-android-sdk.zip` -.. _opencv_android_bin_pack_url: http://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.4.5/OpenCV-2.4.5-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.5_Manager_2.7_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 231fe5afa..243dc35dd 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.5-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.5``. + :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_5, 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.5-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.5``; + :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.5-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.5-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 26ec076f5..5ae506249 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 cb9e0650b..2973b7ec2 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 451a875c8..74e0ff9e0 100644 --- a/doc/tutorials/introduction/linux_eclipse/linux_eclipse.rst +++ b/doc/tutorials/introduction/linux_eclipse/linux_eclipse.rst @@ -245,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 e8b96dab7..1e02b64c9 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/windows_install/windows_install.rst b/doc/tutorials/introduction/windows_install/windows_install.rst index eebda7b06..c29c13aed 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 5826f4dd6..bc61d3386 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 ec227e724..f3058a74d 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/ios/hello/hello.rst b/doc/tutorials/ios/hello/hello.rst index b2a37aa70..8435be54d 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 fd2d9c6e3..c4cde1990 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 051765def..50f734803 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 8fbcc563a..57e0b1b6e 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 146a0ec0b..ba9c2740e 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 c57166b0e..822c54d56 100644 --- a/doc/tutorials/tutorials.rst +++ b/doc/tutorials/tutorials.rst @@ -171,17 +171,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 @@ -235,6 +235,6 @@ As always, we would be happy to hear your comments and receive your contribution ml/table_of_content_ml/table_of_content_ml photo/table_of_content_photo/table_of_content_photo 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 1d5909616..ed3b85a8f 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 5a517dc73..1ed020a35 100644 --- a/include/opencv/cv.h +++ b/include/opencv/cv.h @@ -73,4 +73,3 @@ #endif //CV_IMPL #endif // __OPENCV_OLD_CV_H_ - diff --git a/include/opencv/cxeigen.hpp b/include/opencv/cxeigen.hpp index c503f713d..1f04d1a3a 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/opencv2/opencv.hpp b/include/opencv2/opencv.hpp index 020a45373..3b96bdd36 100644 --- a/include/opencv2/opencv.hpp +++ b/include/opencv2/opencv.hpp @@ -52,6 +52,7 @@ #include "opencv2/calib3d.hpp" #include "opencv2/highgui.hpp" #include "opencv2/contrib.hpp" +#include "opencv2/bioinspired.hpp" #include "opencv2/ml.hpp" #endif diff --git a/ios/configure-device_xcode.sh b/ios/configure-device_xcode.sh deleted file mode 100755 index 8c28a3e90..000000000 --- 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 50e00261d..000000000 --- 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 1441b241b..000000000 --- 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/androidcamera/camera_wrapper/camera_wrapper.cpp b/modules/androidcamera/camera_wrapper/camera_wrapper.cpp index 2d0ebc7a1..ca631fc21 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,7 +387,9 @@ 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; @@ -372,14 +400,24 @@ 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"; int localCameraIndex = cameraId; + if (cameraId == ANY_CAMERA_INDEX) + { + localCameraIndex = 0; + } #if !defined(ANDROID_r2_2_0) - if (cameraId == BACK_CAMERA_INDEX) + else if (cameraId == BACK_CAMERA_INDEX) { LOGD("Back camera selected"); for (int i = 0; i < Camera::getNumberOfCameras(); i++) @@ -450,6 +488,12 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, 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); @@ -471,7 +515,7 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, handler->camera = camera; handler->cameraId = localCameraIndex; - if (prevCameraParameters != 0) + if (prevCameraParameters != NULL) { LOGI("initCameraConnect: Setting paramers from previous camera handler"); camera->setParameters(prevCameraParameters->flatten()); @@ -503,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) { @@ -517,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. @@ -560,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)) @@ -595,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(); @@ -605,7 +648,7 @@ CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, } else { - LOGD("Preview started successfully"); + LOGD("Preview started successfully"); } return handler; @@ -620,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 @@ -863,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; @@ -879,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); @@ -892,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 88c9c4100..430dea2dd 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 8aa25b620..2af7befe3 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 3ce4089be..a265d2e8d 100644 --- a/modules/androidcamera/src/camera_activity.cpp +++ b/modules/androidcamera/src/camera_activity.cpp @@ -434,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 000000000..b0f152cfc --- /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 000000000..6bffcdcf2 --- /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/contrib/doc/retina/images/retinaInput.jpg b/modules/bioinspired/doc/retina/images/retinaInput.jpg similarity index 100% rename from modules/contrib/doc/retina/images/retinaInput.jpg rename to modules/bioinspired/doc/retina/images/retinaInput.jpg diff --git a/modules/contrib/doc/retina/images/retinaOutput_default.jpg b/modules/bioinspired/doc/retina/images/retinaOutput_default.jpg similarity index 100% rename from modules/contrib/doc/retina/images/retinaOutput_default.jpg rename to modules/bioinspired/doc/retina/images/retinaOutput_default.jpg diff --git a/modules/contrib/doc/retina/images/retinaOutput_realistic.jpg b/modules/bioinspired/doc/retina/images/retinaOutput_realistic.jpg similarity index 100% rename from modules/contrib/doc/retina/images/retinaOutput_realistic.jpg rename to modules/bioinspired/doc/retina/images/retinaOutput_realistic.jpg diff --git a/modules/contrib/doc/retina/index.rst b/modules/bioinspired/doc/retina/index.rst similarity index 87% rename from modules/contrib/doc/retina/index.rst rename to modules/bioinspired/doc/retina/index.rst index 5671df77c..242416baa 100644 --- a/modules/contrib/doc/retina/index.rst +++ b/modules/bioinspired/doc/retina/index.rst @@ -7,6 +7,8 @@ Retina ====== .. ocv:class:: Retina : public Algorithm +**Note** : do not forget that the retina model is included in the following namespace : *cv::bioinspired*. + Introduction ++++++++++++ @@ -17,7 +19,7 @@ Class which provides the main controls to the Gipsa/Listic labs human retina mo * peripheral vision for sensitive transient signals detection (motion and events) : the magnocellular pathway. 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]_ (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. +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. **NOTES :** @@ -55,15 +57,20 @@ As observed in this preliminary demo, the retina can be settled up with various 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 - // main method for input frame processing + // main method for input frame processing (all use method, can also perform High Dynamic Range tone mapping) void run (InputArray 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 (OutputArray retinaOutput_parvo); @@ -99,7 +106,13 @@ Here is an overview of the abstract Retina interface, allocate one instance with // 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 +++++++++++ @@ -120,12 +133,20 @@ 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 : +* 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 : .. [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. @@ -138,6 +159,10 @@ This retina filter code includes the research contributions of phd/research coll * 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 ! ======================= @@ -161,12 +186,14 @@ 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 =================== @@ -176,8 +203,8 @@ Here are detailled the main methods to control the retina model Ptr::createRetina +++++++++++++++++++++++++ -.. ocv:function:: Ptr createRetina(Size inputSize) -.. ocv:function:: 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 ) +.. 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 from standardized interfaces : retreive a smart pointer to a Retina instance @@ -185,11 +212,11 @@ Ptr::createRetina :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 + * cv::bioinspired::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... + * cv::bioinspired::RETINA_COLOR_DIAGONAL: color sampling is RGBRGBRGB..., line 2 BRGBRGBRG..., line 3, GBRGBRGBR... - * RETINA_COLOR_BAYER: standard bayer sampling + * 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 @@ -275,7 +302,7 @@ 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 +++++++++++ @@ -286,6 +313,18 @@ Retina::run :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 ++++++++++++++++++++++++++ diff --git a/modules/core/src/precomp.cpp b/modules/bioinspired/include/opencv2/bioinspired.hpp similarity index 91% rename from modules/core/src/precomp.cpp rename to modules/bioinspired/include/opencv2/bioinspired.hpp index e540cc5e8..5f2f8644d 100644 --- a/modules/core/src/precomp.cpp +++ b/modules/bioinspired/include/opencv2/bioinspired.hpp @@ -40,6 +40,11 @@ // //M*/ -#include "precomp.hpp" +#ifndef __OPENCV_BIOINSPIRED_HPP__ +#define __OPENCV_BIOINSPIRED_HPP__ -/* End of file. */ +#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 000000000..40be2854e --- /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 90% rename from modules/contrib/include/opencv2/contrib/retina.hpp rename to modules/bioinspired/include/opencv2/bioinspired/retina.hpp index 579c15d1d..b4fda7038 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,13 +73,12 @@ */ #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 @@ -241,6 +240,14 @@ public: */ 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 @@ -295,8 +302,10 @@ public: virtual void activateContoursProcessing(const bool activate)=0; }; CV_EXPORTS Ptr createRetina(Size inputSize); -CV_EXPORTS 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_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 000000000..6c83f885c --- /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 020b8f04e..7e7b467fa 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 a2ece415d..323bff940 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 22f5214e7..0a4c1ed0d 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 6043b7232..a276d97a4 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 40f71ebe9..f5ffa1a06 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 000000000..541b97032 --- /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/contrib/src/retina.cpp b/modules/bioinspired/src/retina.cpp similarity index 88% rename from modules/contrib/src/retina.cpp rename to modules/bioinspired/src/retina.cpp index de752c024..460433107 100644 --- a/modules/contrib/src/retina.cpp +++ b/modules/bioinspired/src/retina.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,12 @@ #include "retinafilter.hpp" #include #include +#include namespace cv { +namespace bioinspired +{ class RetinaImpl : public Retina { @@ -94,7 +97,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 */ - RetinaImpl(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); + 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(); /** @@ -196,6 +199,14 @@ public: */ 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 @@ -253,14 +264,17 @@ private: // Parameteres setup members RetinaParameters _retinaParameters; // structure of parameters - // Retina model related modules + // 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 HVStools objects to a cv::Mat in CV_8UC1 (gray level picture) or CV_8UC3 (color) format + * 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 @@ -270,22 +284,22 @@ private: 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); - - //! 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); + bool _convertCvMat2ValarrayBuffer(InputArray inputMatToConvert, std::valarray &outputValarrayMatrix); }; // smart pointers allocation : -Ptr createRetina(Size inputSize){ return new RetinaImpl(inputSize); } -Ptr createRetina(Size inputSize, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght){return new RetinaImpl(inputSize, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght);} +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) @@ -294,7 +308,7 @@ RetinaImpl::RetinaImpl(const cv::Size inputSz) _init(inputSz, true, RETINA_COLOR_BAYER, false); } -RetinaImpl::RetinaImpl(const cv::Size inputSz, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) +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); @@ -401,10 +415,10 @@ void RetinaImpl::setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailur printf("%s\n", printSetup().c_str()); } -void RetinaImpl::setup(cv::Retina::RetinaParameters newConfiguration) +void RetinaImpl::setup(Retina::RetinaParameters newConfiguration) { // simply copy structures - memcpy(&_retinaParameters, &newConfiguration, sizeof(cv::Retina::RetinaParameters)); + 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); @@ -526,6 +540,27 @@ void RetinaImpl::run(InputArray inputMatToConvert) 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()) @@ -580,11 +615,11 @@ const Mat RetinaImpl::getParvoRAW() const { } // private method called by constructirs -void RetinaImpl::_init(const cv::Size inputSz, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod, const bool useRetinaLogSampling, const double reductionFactor, const double samplingStrenght) +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", "RetinaImpl.h", 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 @@ -595,8 +630,9 @@ void RetinaImpl::_init(const cv::Size inputSz, const bool colorMode, RETINA_COLO 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); + setup(_retinaParameters); // init retina _retinaFilter->clearAllBuffers(); @@ -623,7 +659,8 @@ void RetinaImpl::_convertValarrayBuffer2cvMat(const std::valarray &grayMa } }else { - const unsigned int doubleNBpixels=_retinaFilter->getOutputNBpixels()*2; + 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 &grayMa cv::Point2d pixel(j,i); cv::Vec3b pixelValues; pixelValues[2]=(unsigned char)*(valarrayPTR); - pixelValues[1]=(unsigned char)*(valarrayPTR+_retinaFilter->getOutputNBpixels()); + pixelValues[1]=(unsigned char)*(valarrayPTR+nbPixels); pixelValues[0]=(unsigned char)*(valarrayPTR+doubleNBpixels); outMat.at(pixel)=pixelValues; @@ -656,15 +693,16 @@ bool RetinaImpl::_convertCvMat2ValarrayBuffer(InputArray inputMat, std::valarray 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[_retinaFilter->getInputNBpixels()*2]), - cv::Mat(inputMatToConvert.size(), dsttype, &outputValarrayMatrix[_retinaFilter->getInputNBpixels()]), + 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) @@ -676,8 +714,8 @@ bool RetinaImpl::_convertCvMat2ValarrayBuffer(InputArray inputMat, std::valarray // 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[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 @@ -701,5 +739,5 @@ void RetinaImpl::activateMovingContoursProcessing(const bool activate){_retinaFi void RetinaImpl::activateContoursProcessing(const bool activate){_retinaFilter->activateContoursProcessing(activate);} -} // end of namespace cv - +}// 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 000000000..c294ebfeb --- /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 000000000..90df0601c --- /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 98% rename from modules/contrib/src/retinacolor.cpp rename to modules/bioinspired/src/retinacolor.cpp index 92cba47af..3fbc55385 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), @@ -720,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 97% rename from modules/contrib/src/retinacolor.hpp rename to modules/bioinspired/src/retinacolor.hpp index ff4a12e40..3fb6be8f9 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 @@ -382,8 +383,7 @@ namespace cv #endif }; -} +}// end of namespace bioinspired +}// end of namespace cv #endif /*RETINACOLOR_HPP_*/ - - diff --git a/modules/bioinspired/src/retinafasttonemapping.cpp b/modules/bioinspired/src/retinafasttonemapping.cpp new file mode 100644 index 000000000..2713d7449 --- /dev/null +++ b/modules/bioinspired/src/retinafasttonemapping.cpp @@ -0,0 +1,316 @@ + +/*#****************************************************************************** + ** 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. + *******************************************************************************/ + +/* + * 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 4cf6019f5..e1e24c89b 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 7fa2a078c..3e204885f 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 21414b4da..827eb709f 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/calib3d/test/test_precomp.cpp b/modules/bioinspired/test/test_main.cpp similarity index 58% rename from modules/calib3d/test/test_precomp.cpp rename to modules/bioinspired/test/test_main.cpp index 5956e13e3..6b2499344 100644 --- a/modules/calib3d/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 000000000..b1672149a --- /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 000000000..b09ce5036 --- /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 0ac8d5196..0c056843d 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 f2fbfd1d9..cb30dc36d 100644 --- a/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst +++ b/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.rst @@ -109,7 +109,16 @@ 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 --------------- @@ -277,6 +286,8 @@ 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: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`` . :param whichImage: Index of the image (1 or 2) that contains the ``points`` . @@ -504,7 +515,7 @@ 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.findCirclesGrid(image, patternSize[, centers[, flags[, blobDetector]]]) -> retval, centers @@ -577,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 ------------------ @@ -879,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 -------------------- @@ -1168,6 +1184,9 @@ StereoBM 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 ------------------ @@ -1199,6 +1218,9 @@ The class implements the modified H. Hirschmuller algorithm [HH08]_ that differs * 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 createStereoSGBM -------------------------- diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index 64462eea8..1a8777b93 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -180,7 +180,7 @@ CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSiz //! 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()); + 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, @@ -262,24 +262,24 @@ CV_EXPORTS Mat findFundamentalMat( InputArray points1, InputArray points2, 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, +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, +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() ); //! 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, diff --git a/modules/calib3d/include/opencv2/calib3d/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d/calib3d.hpp index 302de229b..b3da45edd 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/perf/perf_pnp.cpp b/modules/calib3d/perf/perf_pnp.cpp index e88155729..7a7acb052 100644 --- a/modules/calib3d/perf/perf_pnp.cpp +++ b/modules/calib3d/perf/perf_pnp.cpp @@ -130,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 8552ac3d4..000000000 --- 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 06303bd98..6192c7998 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 b93b4951e..844fde499 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib3d/src/calibinit.cpp @@ -271,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 ); @@ -284,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 ) { @@ -541,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, @@ -627,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 @@ -1109,7 +1109,7 @@ 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++ ) { @@ -1205,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; @@ -1674,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 diff --git a/modules/calib3d/src/calibration.cpp b/modules/calib3d/src/calibration.cpp index bb7863575..893c0e9a9 100644 --- a/modules/calib3d/src/calibration.cpp +++ b/modules/calib3d/src/calibration.cpp @@ -568,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 @@ -584,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 @@ -664,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]); } @@ -682,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]); } @@ -699,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]); } @@ -716,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]); } @@ -736,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]); } @@ -950,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 ); @@ -963,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) @@ -1055,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 ) @@ -1162,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 ) @@ -1310,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); @@ -1403,6 +1403,8 @@ CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, } 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 |= CALIB_FIX_S1_S2_S3_S4; if( flags & CV_CALIB_FIX_K1 ) mask[4] = 0; if( flags & CV_CALIB_FIX_K2 ) @@ -1415,8 +1417,6 @@ CV_IMPL double cvCalibrateCamera2( const CvMat* objectPoints, mask[10] = 0; if( flags & CV_CALIB_FIX_K6 ) mask[11] = 0; - if(!(flags & CV_CALIB_THIN_PRISM_MODEL)) - flags |= CALIB_FIX_S1_S2_S3_S4; if(flags & CALIB_FIX_S1_S2_S3_S4) { @@ -1638,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; @@ -1662,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++ ) @@ -1671,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 ); @@ -1689,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 ); @@ -1729,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, @@ -1740,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 ) @@ -1748,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 ) @@ -1768,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; + } } /* @@ -1842,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); @@ -1908,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]; } } @@ -2080,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++ ) @@ -2439,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 ); @@ -3009,6 +3026,7 @@ static Mat prepareDistCoeffs(Mat& distCoeffs0, int rtype) if( distCoeffs0.size() == Size(1, 4) || distCoeffs0.size() == Size(1, 5) || distCoeffs0.size() == Size(1, 8) || + distCoeffs0.size() == Size(1, 12) || distCoeffs0.size() == Size(4, 1) || distCoeffs0.size() == Size(5, 1) || distCoeffs0.size() == Size(8, 1) || diff --git a/modules/calib3d/src/compat_ptsetreg.cpp b/modules/calib3d/src/compat_ptsetreg.cpp index 74c9e0012..e8f410858 100644 --- a/modules/calib3d/src/compat_ptsetreg.cpp +++ b/modules/calib3d/src/compat_ptsetreg.cpp @@ -53,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; @@ -62,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); } @@ -89,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; @@ -196,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; @@ -428,4 +426,3 @@ CV_IMPL void cvConvertPointsHomogeneous( const CvMat* _src, CvMat* _dst ) dst.convertTo(dst0, dst0.type()); } } - diff --git a/modules/calib3d/src/epnp.cpp b/modules/calib3d/src/epnp.cpp index 7fb63254d..edbcaffd3 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/five-point.cpp b/modules/calib3d/src/five-point.cpp index 7eae2ebf8..992224700 100644 --- a/modules/calib3d/src/five-point.cpp +++ b/modules/calib3d/src/five-point.cpp @@ -436,9 +436,9 @@ cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, double f Mat E; if( method == RANSAC ) - createRANSACPointSetRegistrator(new EMEstimatorCallback, 5, threshold, prob)->run(points1, points2, E, _mask); + 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; } @@ -529,16 +529,25 @@ int cv::recoverPose( InputArray E, InputArray _points1, InputArray _points2, Out mask4 = (Q.row(2) > 0) & mask4; mask4 = (Q.row(2) < dist) & mask4; + mask1 = mask1.t(); + mask2 = mask2.t(); + mask3 = mask3.t(); + mask4 = mask4.t(); + // If _mask is given, then use it to filter outliers. - if (_mask.needed()) + if (!_mask.empty()) { - _mask.create(1, npoints, CV_8U, -1, true); 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()); @@ -548,6 +557,7 @@ int cv::recoverPose( InputArray E, InputArray _points1, InputArray _points2, Out int good2 = countNonZero(mask2); int good3 = countNonZero(mask3); int good4 = countNonZero(mask4); + if (good1 >= good2 && good1 >= good3 && good1 >= good4) { R1.copyTo(_R); diff --git a/modules/calib3d/src/fundam.cpp b/modules/calib3d/src/fundam.cpp index c58e8220a..d1c6e8cd0 100644 --- a/modules/calib3d/src/fundam.cpp +++ b/modules/calib3d/src/fundam.cpp @@ -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; } } @@ -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 ) { @@ -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); } } @@ -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 ) diff --git a/modules/calib3d/src/levmarq.cpp b/modules/calib3d/src/levmarq.cpp index 539c804e2..55704132c 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 92e795472..882868d6b 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 a58b0fa14..57f8d7df8 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/precomp.cpp b/modules/calib3d/src/precomp.cpp deleted file mode 100644 index 3e0ec42de..000000000 --- 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/ptsetreg.cpp b/modules/calib3d/src/ptsetreg.cpp index c92d858dc..aa361a911 100644 --- a/modules/calib3d/src/ptsetreg.cpp +++ b/modules/calib3d/src/ptsetreg.cpp @@ -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 ); @@ -288,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 ); @@ -397,7 +397,8 @@ Ptr createRANSACPointSetRegistrator(const Ptr( + new RANSACPointSetRegistrator(_cb, _modelPoints, _threshold, _confidence, _maxIters)); } @@ -405,7 +406,8 @@ Ptr createLMeDSPointSetRegistrator(const Ptr( + new LMeDSPointSetRegistrator(_cb, _modelPoints, _confidence, _maxIters)); } class Affine3DEstimatorCallback : public PointSetRegistrator::Callback @@ -532,6 +534,5 @@ int cv::estimateAffine3D(InputArray _from, InputArray _to, 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/solvepnp.cpp b/modules/calib3d/src/solvepnp.cpp index e395b0dc5..698302b94 100644 --- a/modules/calib3d/src/solvepnp.cpp +++ b/modules/calib3d/src/solvepnp.cpp @@ -348,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 1fc193a0a..ee131db76 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/calib3d/src/stereobm.cpp @@ -991,7 +991,7 @@ const char* StereoBMImpl::name_ = "StereoMatcher.BM"; 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 508eb59b1..6d75d8f53 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/calib3d/src/stereosgbm.cpp @@ -947,11 +947,12 @@ Ptr createStereoSGBM(int minDisparity, int numDisparities, int SADWi int speckleWindowSize, int speckleRange, int mode) { - return new StereoSGBMImpl(minDisparity, numDisparities, SADWindowSize, - P1, P2, disp12MaxDiff, - preFilterCap, uniquenessRatio, - speckleWindowSize, speckleRange, - mode); + return Ptr( + new StereoSGBMImpl(minDisparity, numDisparities, SADWindowSize, + P1, P2, disp12MaxDiff, + preFilterCap, uniquenessRatio, + speckleWindowSize, speckleRange, + mode)); } Rect getValidDisparityROI( Rect roi1, Rect roi2, @@ -1169,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 59c7c0f2b..b0af3dc46 100644 --- a/modules/calib3d/src/triangulate.cpp +++ b/modules/calib3d/src/triangulate.cpp @@ -240,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 196d428e4..62326e920 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 ff061aacf..f31e2e732 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_badarg.cpp b/modules/calib3d/test/test_cameracalibration_badarg.cpp index 91118e1ed..3edab8bec 100644 --- a/modules/calib3d/test/test_cameracalibration_badarg.cpp +++ b/modules/calib3d/test/test_cameracalibration_badarg.cpp @@ -735,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 3a5ebbc3a..7c0bd34dc 100644 --- a/modules/calib3d/test/test_chessboardgenerator.cpp +++ b/modules/calib3d/test/test_chessboardgenerator.cpp @@ -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_compose_rt.cpp b/modules/calib3d/test/test_compose_rt.cpp index b71288e6d..577cc0627 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_modelest.cpp b/modules/calib3d/test/test_modelest.cpp index 5b0a86016..55cb79eba 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_precomp.hpp b/modules/calib3d/test/test_precomp.hpp index 3fe4480d5..d670a4c22 100644 --- a/modules/calib3d/test/test_precomp.hpp +++ b/modules/calib3d/test/test_precomp.hpp @@ -21,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 3b44566ab..daf89e0f0 100644 --- a/modules/calib3d/test/test_reproject_image_to_3d.cpp +++ b/modules/calib3d/test/test_reproject_image_to_3d.cpp @@ -173,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 c0aff188d..ae744a4d7 100644 --- a/modules/calib3d/test/test_solvepnp_ransac.cpp +++ b/modules/calib3d/test/test_solvepnp_ransac.cpp @@ -276,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); } @@ -295,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); } @@ -306,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_undistort_points.cpp b/modules/calib3d/test/test_undistort_points.cpp index c1ace3d4d..5dabd213d 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/doc/contrib.rst b/modules/contrib/doc/contrib.rst index 798d38d5b..de14d33ef 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/facerec_api.rst b/modules/contrib/doc/facerec/facerec_api.rst index e16d15e62..c2c7f56d0 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 -------------- @@ -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 +++++++++++++++++++++++ diff --git a/modules/contrib/doc/facerec/facerec_tutorial.rst b/modules/contrib/doc/facerec/facerec_tutorial.rst index 16b425d7e..cbfb41797 100644 --- a/modules/contrib/doc/facerec/facerec_tutorial.rst +++ b/modules/contrib/doc/facerec/facerec_tutorial.rst @@ -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 ce8a15e67..b871448c5 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 e56762ea4..94aa36fbe 100644 --- a/modules/contrib/doc/facerec/src/CMakeLists.txt +++ b/modules/contrib/doc/facerec/src/CMakeLists.txt @@ -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/tutorial/facerec_gender_classification.rst b/modules/contrib/doc/facerec/tutorial/facerec_gender_classification.rst index 0c7398d2f..770083170 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 7948bcd73..2d0b65dff 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 b692fe513..76e76eebe 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 2f2ad4074..e2f157a07 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 d5f2d0080..103bd0f3f 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 be83152db..75c6f3db0 100644 --- a/modules/contrib/include/opencv2/contrib.hpp +++ b/modules/contrib/include/opencv2/contrib.hpp @@ -633,7 +633,6 @@ 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 diff --git a/modules/contrib/src/adaptiveskindetector.cpp b/modules/contrib/src/adaptiveskindetector.cpp index 1448e6384..092e48cb4 100644 --- a/modules/contrib/src/adaptiveskindetector.cpp +++ b/modules/contrib/src/adaptiveskindetector.cpp @@ -286,5 +286,3 @@ void CvAdaptiveSkinDetector::Histogram::mergeWith(CvAdaptiveSkinDetector::Histog } } }; - - diff --git a/modules/contrib/src/ba.cpp b/modules/contrib/src/ba.cpp index ff58073fc..9a8002e96 100644 --- a/modules/contrib/src/ba.cpp +++ b/modules/contrib/src/ba.cpp @@ -746,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 ); diff --git a/modules/contrib/src/bowmsctrainer.cpp b/modules/contrib/src/bowmsctrainer.cpp index c1e945f9b..305769120 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/chowliutree.cpp b/modules/contrib/src/chowliutree.cpp index 8c6acabdc..d4aed5383 100644 --- a/modules/contrib/src/chowliutree.cpp +++ b/modules/contrib/src/chowliutree.cpp @@ -287,4 +287,3 @@ bool ChowLiuTree::reduceEdgesToMinSpan(std::list& edges) { } } - diff --git a/modules/contrib/src/colortracker.cpp b/modules/contrib/src/colortracker.cpp index c1d91bb9b..a3eeb052b 100644 --- a/modules/contrib/src/colortracker.cpp +++ b/modules/contrib/src/colortracker.cpp @@ -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 a80f6f5e1..317867a59 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 49d09d1bf..27807290a 100644 --- a/modules/contrib/src/detection_based_tracker.cpp +++ b/modules/contrib/src/detection_based_tracker.cpp @@ -128,7 +128,7 @@ cv::DetectionBasedTracker::SeparateDetectionWork::SeparateDetectionWork(Detectio stateThread(STATE_THREAD_STOPPED), timeWhenDetectingThreadStartedWork(-1) { - CV_Assert(!_detector.empty()); + CV_Assert(_detector); cascadeInThread = _detector; @@ -462,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); @@ -483,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(); } @@ -501,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); } @@ -589,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; @@ -597,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(); @@ -876,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; @@ -892,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 d1050ebb7..1bea74e89 100644 --- a/modules/contrib/src/facerec.cpp +++ b/modules/contrib/src/facerec.cpp @@ -851,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", @@ -894,7 +894,7 @@ CV_INIT_ALGORITHM(LBPH, "FaceRecognizer.LBPH", bool initModule_contrib() { - Ptr efaces = createEigenfaces_hidden(), ffaces = createFisherfaces_hidden(), lbph = createLBPH_hidden(); + 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 4350aec46..795c1a08f 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() @@ -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 7ad8cd838..5e5ebc7e9 100644 --- a/modules/contrib/src/fuzzymeanshifttracker.cpp +++ b/modules/contrib/src/fuzzymeanshifttracker.cpp @@ -721,4 +721,3 @@ void CvFuzzyMeanShiftTracker::track(IplImage *maskImage, IplImage *depthMap, int searchMode = tsTracking; } }; - diff --git a/modules/contrib/src/hybridtracker.cpp b/modules/contrib/src/hybridtracker.cpp index 23a6ecbba..d93f76d0d 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 f64502e43..7f583558e 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 String& path, const String & exten, bool addPath ) + std::vector Directory::GetListFiles( const String& path, const String & exten, bool addPath ) { std::vector list; list.clear(); 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 @@ -75,10 +99,22 @@ namespace cv 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); } diff --git a/modules/contrib/src/lda.cpp b/modules/contrib/src/lda.cpp index 60693fc77..fe60e8923 100644 --- a/modules/contrib/src/lda.cpp +++ b/modules/contrib/src/lda.cpp @@ -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 70c7437bb..8327b0a2d 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/precomp.cpp b/modules/contrib/src/precomp.cpp deleted file mode 100644 index 3e0ec42de..000000000 --- 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/stereovar.cpp b/modules/contrib/src/stereovar.cpp index 54dd82ac9..b2141b1f1 100644 --- a/modules/contrib/src/stereovar.cpp +++ b/modules/contrib/src/stereovar.cpp @@ -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.hpp b/modules/contrib/test/test_precomp.hpp index de9e283ee..992ff28df 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 8b3c6c770..b83a59149 100644 --- a/modules/core/CMakeLists.txt +++ b/modules/core/CMakeLists.txt @@ -1,9 +1,13 @@ set(the_description "The Core Functionality") -ocv_add_module(core ${ZLIB_LIBRARIES}) -ocv_module_include_directories(${ZLIB_INCLUDE_DIR}) +ocv_add_module(core ${ZLIB_LIBRARIES} OPTIONAL opencv_cudev) +ocv_module_include_directories(${ZLIB_INCLUDE_DIRS}) + +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() if(HAVE_CUDA) - ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef) + 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") diff --git a/modules/core/doc/basic_structures.rst b/modules/core/doc/basic_structures.rst index 70c7c0ebe..93e7ca479 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,6 +307,28 @@ 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() @@ -217,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 -------------------------- @@ -321,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; @@ -333,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; }; @@ -418,6 +638,48 @@ The keypoint constructors :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 @@ -448,188 +710,335 @@ train descriptor index, train image index, and distance between descriptors. :: }; - -.. _Ptr: - 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 { @@ -659,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 @@ -879,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: @@ -1141,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 @@ -1542,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. @@ -2209,7 +2621,6 @@ Various SparseMat constructors. :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 --------------------- @@ -2224,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. @@ -2251,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. @@ -2343,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 @@ -2371,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. @@ -2380,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``, @@ -2393,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_ @@ -2461,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: @@ -2599,7 +3108,7 @@ Creates algorithm instance by 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"); @@ -2615,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 557e92eb4..dc9b28799 100644 --- a/modules/core/doc/clustering.rst +++ b/modules/core/doc/clustering.rst @@ -15,12 +15,18 @@ Finds centers of clusters and groups input samples around the clusters. :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(). @@ -35,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 @@ -56,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 64c72020a..c1f69f4e5 100644 --- a/modules/core/doc/command_line_parser.rst +++ b/modules/core/doc/command_line_parser.rst @@ -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 90caeebc7..73bfc3536 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 17e983b6b..258cfe6ef 100644 --- a/modules/core/doc/drawing_functions.rst +++ b/modules/core/doc/drawing_functions.rst @@ -26,6 +26,10 @@ 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. @@ -225,6 +229,8 @@ Calculates the width and height of a text string. :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. @@ -233,6 +239,12 @@ 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: :: @@ -547,6 +559,12 @@ 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 @@ -584,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 1f2abd480..0f3df5d12 100644 --- a/modules/core/doc/dynamic_structures.rst +++ b/modules/core/doc/dynamic_structures.rst @@ -1580,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 582f1d00d..6d9fdfca5 100644 --- a/modules/core/doc/intro.rst +++ b/modules/core/doc/intro.rst @@ -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: diff --git a/modules/core/doc/old_basic_structures.rst b/modules/core/doc/old_basic_structures.rst index d86daa4a5..906306dcb 100644 --- a/modules/core/doc/old_basic_structures.rst +++ b/modules/core/doc/old_basic_structures.rst @@ -1677,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/opengl_interop.rst b/modules/core/doc/opengl_interop.rst new file mode 100644 index 000000000..5267c4d45 --- /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 d2c0bba14..d38f57ac3 100644 --- a/modules/core/doc/operations_on_arrays.rst +++ b/modules/core/doc/operations_on_arrays.rst @@ -512,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: @@ -971,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 @@ -1033,6 +1039,8 @@ Returns the determinant of a square floating-point matrix. :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. @@ -2159,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 -------- 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 9cecb11a0..d5052fa5a 100644 --- a/modules/core/doc/utility_and_system_functions_and_macros.rst +++ b/modules/core/doc/utility_and_system_functions_and_macros.rst @@ -165,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. @@ -180,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_``: :: @@ -241,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. diff --git a/modules/core/doc/xml_yaml_persistence.rst b/modules/core/doc/xml_yaml_persistence.rst index b3938b75c..cf3cfb447 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. --------------------------------- @@ -181,6 +185,17 @@ Opens a file. .. 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. diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index 9833315d5..c7f07ed45 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -670,6 +670,10 @@ public: //! 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 diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index cf7b29cad..ed8bd29a1 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -430,5 +430,3 @@ cv::Affine3::operator Eigen::Transform() const #endif /* __cplusplus */ #endif /* __OPENCV_CORE_AFFINE3_HPP__ */ - - diff --git a/modules/core/include/opencv2/core/base.hpp b/modules/core/include/opencv2/core/base.hpp index 637ecdf51..013f573a6 100644 --- a/modules/core/include/opencv2/core/base.hpp +++ b/modules/core/include/opencv2/core/base.hpp @@ -449,15 +449,15 @@ _AccTp normInf(const _Tp* a, const _Tp* b, int n) ////////////////// forward declarations for important OpenCV types ////////////////// -template class CV_EXPORTS Vec; -template class CV_EXPORTS Matx; +template class Vec; +template class Matx; -template class CV_EXPORTS Complex; -template class CV_EXPORTS Point_; -template class CV_EXPORTS Point3_; -template class CV_EXPORTS Size_; -template class CV_EXPORTS Rect_; -template class CV_EXPORTS Scalar_; +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; @@ -472,16 +472,16 @@ class CV_EXPORTS MatExpr; class CV_EXPORTS SparseMat; typedef Mat MatND; -template class CV_EXPORTS Mat_; -template class CV_EXPORTS SparseMat_; +template class Mat_; +template class SparseMat_; class CV_EXPORTS MatConstIterator; class CV_EXPORTS SparseMatIterator; class CV_EXPORTS SparseMatConstIterator; -template class CV_EXPORTS MatIterator_; -template class CV_EXPORTS MatConstIterator_; -template class CV_EXPORTS SparseMatIterator_; -template class CV_EXPORTS SparseMatConstIterator_; +template class MatIterator_; +template class MatConstIterator_; +template class SparseMatIterator_; +template class SparseMatConstIterator_; namespace ogl { @@ -498,6 +498,11 @@ namespace gpu class CV_EXPORTS Event; } +namespace cudev +{ + template class GpuMat_; +} + } // cv #endif //__OPENCV_CORE_BASE_HPP__ diff --git a/modules/core/include/opencv2/core/core_c.h b/modules/core/include/opencv2/core/core_c.h index 0ed3edec6..ca8413ee2 100644 --- a/modules/core/include/opencv2/core/core_c.h +++ b/modules/core/include/opencv2/core/core_c.h @@ -1882,13 +1882,13 @@ CV_EXPORTS void insertImageCOI(InputArray coiimg, CvArr* arr, int coi=-1); -//////// specializied implementations of Ptr::delete_obj() for classic OpenCV types //////// +////// specialized implementations of DefaultDeleter::operator() 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 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 ////////////// @@ -1906,7 +1906,7 @@ typedef Ptr MemStorage; i.e. no constructors or destructors are called for the sequence elements. */ -template class CV_EXPORTS Seq +template class Seq { public: typedef SeqIterator<_Tp> iterator; @@ -1989,7 +1989,7 @@ public: /*! STL-style Sequence Iterator inherited from the CvSeqReader structure */ -template class CV_EXPORTS SeqIterator : public CvSeqReader +template class SeqIterator : public CvSeqReader { public: //! the default constructor diff --git a/modules/core/include/opencv2/core/cuda/color.hpp b/modules/core/include/opencv2/core/cuda/color.hpp index a2b772d8b..d5f94c92a 100644 --- a/modules/core/include/opencv2/core/cuda/color.hpp +++ b/modules/core/include/opencv2/core/cuda/color.hpp @@ -107,25 +107,25 @@ namespace cv { namespace gpu { namespace cudev #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 diff --git a/modules/core/include/opencv2/core/cuda/limits.hpp b/modules/core/include/opencv2/core/cuda/limits.hpp index 4b265da0e..0439de795 100644 --- a/modules/core/include/opencv2/core/cuda/limits.hpp +++ b/modules/core/include/opencv2/core/cuda/limits.hpp @@ -43,193 +43,80 @@ #ifndef __OPENCV_GPU_LIMITS_GPU_HPP__ #define __OPENCV_GPU_LIMITS_GPU_HPP__ -#include +#include +#include #include "common.hpp" namespace cv { namespace gpu { namespace cudev { - 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; - 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 +{ + __device__ __forceinline__ static bool min() { return false; } + __device__ __forceinline__ static bool max() { return true; } + static const bool is_signed = false; +}; - 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 +{ + __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 - { - 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 +{ + __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 - { - 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 +{ + __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 - { - 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 +{ + __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 - { - 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 +{ + __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 - { - 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 +{ + __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 - { - 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 +{ + __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; +}; - 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 cudev { #endif // __OPENCV_GPU_LIMITS_GPU_HPP__ diff --git a/modules/core/include/opencv2/core/cvdef.h b/modules/core/include/opencv2/core/cvdef.h index 2fba1351f..46f294962 100644 --- a/modules/core/include/opencv2/core/cvdef.h +++ b/modules/core/include/opencv2/core/cvdef.h @@ -84,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 @@ -149,7 +149,12 @@ # 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 @@ -196,8 +201,10 @@ #if !defined _MSC_VER && !defined __BORLANDC__ # if defined __cplusplus && __cplusplus >= 201103L # include + typedef std::uint32_t uint; # else # include + typedef uint32_t uint; # endif #else typedef unsigned uint; @@ -364,7 +371,7 @@ CV_INLINE int cvRound( double value ) return t; #elif defined _MSC_VER && defined _M_ARM && defined HAVE_TEGRA_OPTIMIZATION TEGRA_ROUND(value); -#elif defined HAVE_LRINT || defined CV_ICC || defined __GNUC__ +#elif defined CV_ICC || defined __GNUC__ # ifdef HAVE_TEGRA_OPTIMIZATION TEGRA_ROUND(value); # else diff --git a/modules/core/include/opencv2/core/cvstd.hpp b/modules/core/include/opencv2/core/cvstd.hpp index 0232c6d08..afdeb2549 100644 --- a/modules/core/include/opencv2/core/cvstd.hpp +++ b/modules/core/include/opencv2/core/cvstd.hpp @@ -127,7 +127,7 @@ CV_EXPORTS void fastFree(void* ptr); /*! The STL-compilant memory Allocator based on cv::fastMalloc() and cv::fastFree() */ -template class CV_EXPORTS Allocator +template class Allocator { public: typedef _Tp value_type; @@ -158,69 +158,176 @@ public: size_type max_size() const { return cv::max(static_cast<_Tp>(-1)/sizeof(_Tp), 1); } }; - - -//////////////////// 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<> CV_EXPORTS 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 +namespace detail { -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; +// Metafunction to avoid taking a reference to void. +template +struct RefOrVoid { typedef T& type; }; - //! helper operators making "Ptr ptr" use very similar to "T* ptr". - _Tp* operator -> (); - const _Tp* operator -> () const; +template<> +struct RefOrVoid{ typedef void type; }; - operator _Tp* (); - operator const _Tp*() const; +template<> +struct RefOrVoid{ typedef const void type; }; - _Tp* obj; //< the object pointer. - int* refcount; //< the associated reference counter +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 //////////////////////////////// @@ -324,176 +431,6 @@ private: }; - -/////////////////////////// cv::Ptr implementation /////////////////////////// - -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 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 inline -Ptr<_Tp>::~Ptr() -{ - release(); -} - -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(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 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 static inline -bool operator == (const Ptr<_Tp>& a, const Ptr<_Tp2>& b) -{ - return a.refcount == b.refcount; -} - -template static inline -bool operator != (const Ptr<_Tp>& a, const Ptr<_Tp2>& b) -{ - return a.refcount != b.refcount; -} - - - ////////////////////////// cv::String implementation ///////////////////////// inline @@ -580,6 +517,8 @@ String::~String() 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_; @@ -938,4 +877,6 @@ namespace cv } } +#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 index 3f29a1b67..8642b7442 100644 --- a/modules/core/include/opencv2/core/cvstd.inl.hpp +++ b/modules/core/include/opencv2/core/cvstd.inl.hpp @@ -247,4 +247,4 @@ std::ostream& operator << (std::ostream& out, const Rect_<_Tp>& rect) #endif // OPENCV_NOSTL } // cv -#endif // __OPENCV_CORE_CVSTDINL_HPP__ \ No newline at end of file +#endif // __OPENCV_CORE_CVSTDINL_HPP__ diff --git a/modules/core/include/opencv2/core/gpu.hpp b/modules/core/include/opencv2/core/gpu.hpp index 775a9d026..dfd4dd92a 100644 --- a/modules/core/include/opencv2/core/gpu.hpp +++ b/modules/core/include/opencv2/core/gpu.hpp @@ -375,19 +375,6 @@ public: //! returns true if stream object is not default (!= 0) operator bool_type() const; - // obsolete methods - - void enqueueDownload(const GpuMat& src, OutputArray dst); - - void enqueueUpload(InputArray src, GpuMat& dst); - - void enqueueCopy(const GpuMat& src, OutputArray dst); - - void enqueueMemSet(GpuMat& src, Scalar val); - void enqueueMemSet(GpuMat& src, Scalar val, InputArray mask); - - void enqueueConvert(const GpuMat& src, OutputArray dst, int dtype, double alpha = 1.0, double beta = 0.0); - class Impl; private: @@ -529,10 +516,10 @@ public: size_t totalConstMem() const; //! major compute capability - int major() const; + int majorVersion() const; //! minor compute capability - int minor() const; + int minorVersion() const; //! alignment requirement for textures size_t textureAlignment() const; @@ -679,12 +666,6 @@ CV_EXPORTS void printShortCudaDeviceInfo(int device); }} // namespace cv { namespace gpu { -namespace cv { - -template <> CV_EXPORTS void Ptr::delete_obj(); -template <> CV_EXPORTS void Ptr::delete_obj(); - -} #include "opencv2/core/gpu.inl.hpp" diff --git a/modules/core/include/opencv2/core/gpu.inl.hpp b/modules/core/include/opencv2/core/gpu.inl.hpp index b44c2b151..13861170c 100644 --- a/modules/core/include/opencv2/core/gpu.inl.hpp +++ b/modules/core/include/opencv2/core/gpu.inl.hpp @@ -525,42 +525,6 @@ void swap(CudaMem& a, CudaMem& b) //////////////////////////////// Stream /////////////////////////////// -inline -void Stream::enqueueDownload(const GpuMat& src, OutputArray dst) -{ - src.download(dst, *this); -} - -inline -void Stream::enqueueUpload(InputArray src, GpuMat& dst) -{ - dst.upload(src, *this); -} - -inline -void Stream::enqueueCopy(const GpuMat& src, OutputArray dst) -{ - src.copyTo(dst, *this); -} - -inline -void Stream::enqueueMemSet(GpuMat& src, Scalar val) -{ - src.setTo(val, *this); -} - -inline -void Stream::enqueueMemSet(GpuMat& src, Scalar val, InputArray mask) -{ - src.setTo(val, mask, *this); -} - -inline -void Stream::enqueueConvert(const GpuMat& src, OutputArray dst, int dtype, double alpha, double beta) -{ - src.convertTo(dst, dtype, alpha, beta, *this); -} - inline Stream::Stream(const Ptr& impl) : impl_(impl) @@ -619,7 +583,7 @@ size_t DeviceInfo::totalMemory() const inline bool DeviceInfo::supports(FeatureSet feature_set) const { - int version = major() * 10 + minor(); + int version = majorVersion() * 10 + minorVersion(); return version >= feature_set; } diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 8c9b10cea..c132be945 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -78,7 +78,8 @@ public: EXPR = 6 << KIND_SHIFT, OPENGL_BUFFER = 7 << KIND_SHIFT, CUDA_MEM = 8 << KIND_SHIFT, - GPU_MAT = 9 << KIND_SHIFT + GPU_MAT = 9 << KIND_SHIFT, + OCL_MAT =10 << KIND_SHIFT }; _InputArray(); @@ -95,6 +96,7 @@ public: _InputArray(const gpu::GpuMat& d_mat); _InputArray(const ogl::Buffer& buf); _InputArray(const gpu::CudaMem& cuda_mem); + template _InputArray(const cudev::GpuMat_<_Tp>& m); virtual Mat getMat(int i=-1) const; virtual void getMatVector(std::vector& mv) const; @@ -143,6 +145,7 @@ public: _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); @@ -155,6 +158,7 @@ public: _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); @@ -827,7 +831,7 @@ protected: 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 +template class Mat_ : public Mat { public: typedef _Tp value_type; @@ -1129,8 +1133,6 @@ public: //! 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 @@ -1356,7 +1358,7 @@ public: m_.ref(2) += m_(3); // equivalent to m.ref(2) += m.value(3); \endcode */ -template class CV_EXPORTS SparseMat_ : public SparseMat +template class SparseMat_ : public SparseMat { public: typedef SparseMatIterator_<_Tp> iterator; @@ -1728,7 +1730,7 @@ public: 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> +template class SparseMatIterator_ : public SparseMatConstIterator_<_Tp> { public: diff --git a/modules/core/include/opencv2/core/matx.hpp b/modules/core/include/opencv2/core/matx.hpp index 6115e3de1..86a35cd75 100644 --- a/modules/core/include/opencv2/core/matx.hpp +++ b/modules/core/include/opencv2/core/matx.hpp @@ -77,10 +77,11 @@ 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 CV_EXPORTS Matx +template class Matx { public: enum { depth = DataType<_Tp>::depth, @@ -162,6 +163,9 @@ public: //! 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); @@ -174,6 +178,7 @@ public: 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); @@ -281,7 +286,7 @@ template static double norm(const Matx<_Tp, m, n>& M 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> +template class Vec : public Matx<_Tp, cn, 1> { public: typedef _Tp value_type; @@ -746,6 +751,13 @@ Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_Mul 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) { @@ -773,6 +785,12 @@ 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 { @@ -1337,4 +1355,4 @@ template inline Vec<_Tp, 4>& operator *= (Vec<_Tp, 4>& v1, const V } // cv -#endif // __OPENCV_CORE_MATX_HPP__ \ No newline at end of file +#endif // __OPENCV_CORE_MATX_HPP__ diff --git a/modules/core/include/opencv2/core/opengl.hpp b/modules/core/include/opencv2/core/opengl.hpp index a4ee091f7..0a4b454c8 100644 --- a/modules/core/include/opencv2/core/opengl.hpp +++ b/modules/core/include/opencv2/core/opengl.hpp @@ -283,12 +283,6 @@ CV_EXPORTS void setGlDevice(int device = 0); }} -namespace cv { - -template <> CV_EXPORTS void Ptr::delete_obj(); -template <> CV_EXPORTS void Ptr::delete_obj(); - -} //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// diff --git a/modules/core/include/opencv2/core/operations.hpp b/modules/core/include/opencv2/core/operations.hpp index 7d39154a1..f8aeddfb1 100644 --- a/modules/core/include/opencv2/core/operations.hpp +++ b/modules/core/include/opencv2/core/operations.hpp @@ -445,14 +445,14 @@ int print(const Matx<_Tp, m, n>& matx, FILE* stream = stdout) template inline Ptr<_Tp> Algorithm::create(const String& name) { - return _create(name).ptr<_Tp>(); + return _create(name).dynamicCast<_Tp>(); } template inline void Algorithm::set(const char* _name, const Ptr<_Tp>& value) { - Ptr algo_ptr = value. template ptr(); - if (algo_ptr.empty()) { + 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); @@ -468,7 +468,7 @@ template inline void Algorithm::setAlgorithm(const char* _name, const Ptr<_Tp>& value) { Ptr algo_ptr = value. template ptr(); - if (algo_ptr.empty()) { + 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); diff --git a/modules/core/include/opencv2/core/persistence.hpp b/modules/core/include/opencv2/core/persistence.hpp index e81401cae..f5687614b 100644 --- a/modules/core/include/opencv2/core/persistence.hpp +++ b/modules/core/include/opencv2/core/persistence.hpp @@ -186,7 +186,7 @@ public: //! 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); + FileStorage(CvFileStorage* fs, bool owning=true); //! the destructor. calls release() virtual ~FileStorage(); @@ -209,9 +209,9 @@ public: CV_WRAP FileNode operator[](const char* nodename) const; //! returns pointer to the underlying C FileStorage structure - CvFileStorage* operator *() { return fs; } + CvFileStorage* operator *() { return fs.get(); } //! returns pointer to the underlying C FileStorage structure - const CvFileStorage* operator *() const { return fs; } + 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() @@ -226,7 +226,7 @@ public: int state; //!< the writer state }; -template<> CV_EXPORTS void Ptr::delete_obj(); +template<> CV_EXPORTS void DefaultDeleter::operator ()(CvFileStorage* obj) const; /*! File Storage Node class @@ -406,6 +406,59 @@ CV_EXPORTS void read(const FileNode& node, Mat& mat, const Mat& default_mat = Ma 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); diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index 12961b32c..a1cc0e5c8 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -121,15 +121,24 @@ namespace cv 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 ::cv::Algorithm* create##classname##_hidden() \ + static inline ::cv::Algorithm* create##classname##_hidden() \ { \ return new classname; \ } \ \ - static ::cv::AlgorithmInfo& classname##_info() \ + 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; \ 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 000000000..989724281 --- /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/types.hpp b/modules/core/include/opencv2/core/types.hpp index 05cf5052f..9252cad14 100644 --- a/modules/core/include/opencv2/core/types.hpp +++ b/modules/core/include/opencv2/core/types.hpp @@ -68,7 +68,7 @@ namespace cv 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 +template class Complex { public: @@ -120,7 +120,7 @@ public: 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_ +template class Point_ { public: typedef _Tp value_type; @@ -191,7 +191,7 @@ public: \see cv::Point3i, cv::Point3f and cv::Point3d */ -template class CV_EXPORTS Point3_ +template class Point3_ { public: typedef _Tp value_type; @@ -256,7 +256,7 @@ public: 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_ +template class Size_ { public: typedef _Tp value_type; @@ -314,7 +314,7 @@ public: 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_ +template class Rect_ { public: typedef _Tp value_type; @@ -470,7 +470,7 @@ public: 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> +template class Scalar_ : public Vec<_Tp, 4> { public: //! various constructors @@ -551,18 +551,18 @@ public: 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()); + 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 - 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); + 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) - static float overlap(const KeyPoint& kp1, const KeyPoint& kp2); + 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 @@ -1922,4 +1922,4 @@ TermCriteria::TermCriteria(int _type, int _maxCount, double _epsilon) } // cv -#endif //__OPENCV_CORE_TYPES_HPP__ \ No newline at end of file +#endif //__OPENCV_CORE_TYPES_HPP__ diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index d2942f8c5..c96a0aaf9 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -80,7 +80,7 @@ namespace cv } \endcode */ -template class CV_EXPORTS AutoBuffer +template class AutoBuffer { public: typedef _Tp value_type; @@ -116,8 +116,8 @@ protected: _Tp* ptr; //! size of the real buffer size_t sz; - //! pre-allocated buffer - _Tp buf[fixed_size]; + //! 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. diff --git a/modules/core/include/opencv2/core/version.hpp b/modules/core/include/opencv2/core/version.hpp index 916d173ba..203503eca 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 691c6f7c4..63cb06b63 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 64a8dd8bd..1308b7bf3 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_main.cpp b/modules/core/perf/perf_main.cpp index 79c28a645..7c899c244 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 d82941a92..e7e8d2fe3 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 8552ac3d4..000000000 --- a/modules/core/perf/perf_precomp.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "perf_precomp.hpp" diff --git a/modules/core/perf/perf_stat.cpp b/modules/core/perf/perf_stat.cpp index b7fc43d12..6b5f0ff52 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 d0c6f5c92..ff67a5df1 100644 --- a/modules/core/src/algorithm.cpp +++ b/modules/core/src/algorithm.cpp @@ -163,7 +163,7 @@ Ptr Algorithm::_create(const String& name) Algorithm::Constructor c = 0; if( !alglist().find(name, c) ) return Ptr(); - return c(); + return Ptr(c()); } Algorithm::Algorithm() @@ -490,7 +490,7 @@ void AlgorithmInfo::read(Algorithm* algo, const FileNode& fn) const else if( p.type == Param::ALGORITHM ) { Ptr nestedAlgo = Algorithm::_create((String)n["name"]); - CV_Assert( !nestedAlgo.empty() ); + CV_Assert( nestedAlgo ); nestedAlgo->read(n); info->set(algo, pname.c_str(), p.type, &nestedAlgo, true); } diff --git a/modules/core/src/alloc.cpp b/modules/core/src/alloc.cpp index c830df23c..8e218738b 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); } diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index 98b67aabf..313d06d88 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,24 +1187,24 @@ 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 ); } @@ -1482,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, @@ -1549,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()); } /****************************************************************************************\ @@ -1844,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); } /****************************************************************************************\ @@ -2026,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; +} } @@ -2039,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); } @@ -2109,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]); @@ -2187,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; @@ -2290,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); } @@ -2299,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) { @@ -2337,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; } @@ -2369,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 ) { @@ -2546,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]; +} } @@ -2590,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 60ac84865..2ad7b1216 100644 --- a/modules/core/src/array.cpp +++ b/modules/core/src/array.cpp @@ -3190,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 4f4c8db4a..b082faee6 100644 --- a/modules/core/src/command_line_parser.cpp +++ b/modules/core/src/command_line_parser.cpp @@ -136,18 +136,13 @@ void CommandLineParser::getByIndex(int index, bool space_delete, int type, void* 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 String& keys) diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index f5d6e9998..5cd689460 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 ) { @@ -947,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)]; } 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)]; } @@ -1057,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 ) @@ -1376,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/cuda/gpu_mat.cu b/modules/core/src/cuda/gpu_mat.cu new file mode 100644 index 000000000..0db158421 --- /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 7de5205ec..000000000 --- a/modules/core/src/cuda/matrix_operations.cu +++ /dev/null @@ -1,296 +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/core/cuda/saturate_cast.hpp" -#include "opencv2/core/cuda/transform.hpp" -#include "opencv2/core/cuda/functional.hpp" -#include "opencv2/core/cuda/type_traits.hpp" -#include "opencv2/core/cuda/vec_traits.hpp" - -#include "matrix_operations.hpp" - -namespace cv { namespace gpu { namespace cudev -{ - /////////////////////////////////////////////////////////////////////////// - // copyWithMask - - template - void copyWithMask(PtrStepSzb src, PtrStepSzb dst, int cn, PtrStepSzb mask, bool multiChannelMask, cudaStream_t stream) - { - if (multiChannelMask) - cv::gpu::cudev::transform((PtrStepSz) src, (PtrStepSz) dst, identity(), SingleMask(mask), stream); - else - cv::gpu::cudev::transform((PtrStepSz) src, (PtrStepSz) dst, identity(), SingleMaskChannels(mask, cn), stream); - } - - void copyWithMask(PtrStepSzb src, PtrStepSzb dst, size_t elemSize1, int cn, PtrStepSzb mask, bool multiChannelMask, cudaStream_t stream) - { - typedef void (*func_t)(PtrStepSzb src, PtrStepSzb dst, int cn, PtrStepSzb mask, bool multiChannelMask, cudaStream_t stream); - - static const func_t tab[] = - { - 0, - copyWithMask, - copyWithMask, - 0, - copyWithMask, - 0, - 0, - 0, - copyWithMask - }; - - const func_t func = tab[elemSize1]; - CV_DbgAssert( func != 0 ); - - func(src, dst, cn, mask, multiChannelMask, stream); - } - - /////////////////////////////////////////////////////////////////////////// - // set - - template - __global__ void set(PtrStepSz mat, const Mask mask, const int channels, const typename TypeVec::vec_type value) - { - const int x = blockIdx.x * blockDim.x + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (x >= mat.cols * channels || y >= mat.rows) - return; - - const T scalar[4] = {value.x, value.y, value.z, value.w}; - - if (mask(y, x / channels)) - mat(y, x) = scalar[x % channels]; - } - - template - void set(PtrStepSz mat, const T* scalar, int channels, cudaStream_t stream) - { - typedef typename TypeVec::vec_type scalar_t; - - dim3 block(32, 8); - dim3 grid(divUp(mat.cols * channels, block.x), divUp(mat.rows, block.y)); - - set<<>>(mat, WithOutMask(), channels, VecTraits::make(scalar)); - cudaSafeCall( cudaGetLastError() ); - - if (stream == 0) - cudaSafeCall ( cudaDeviceSynchronize() ); - } - - template void set(PtrStepSz mat, const uchar* scalar, int channels, cudaStream_t stream); - template void set(PtrStepSz mat, const schar* scalar, int channels, cudaStream_t stream); - template void set(PtrStepSz mat, const ushort* scalar, int channels, cudaStream_t stream); - template void set(PtrStepSz mat, const short* scalar, int channels, cudaStream_t stream); - template void set(PtrStepSz mat, const int* scalar, int channels, cudaStream_t stream); - template void set(PtrStepSz mat, const float* scalar, int channels, cudaStream_t stream); - template void set(PtrStepSz mat, const double* scalar, int channels, cudaStream_t stream); - - template - void set(PtrStepSz mat, const T* scalar, PtrStepSzb mask, int channels, cudaStream_t stream) - { - typedef typename TypeVec::vec_type scalar_t; - - dim3 block(32, 8); - dim3 grid(divUp(mat.cols * channels, block.x), divUp(mat.rows, block.y)); - - set<<>>(mat, SingleMask(mask), channels, VecTraits::make(scalar)); - cudaSafeCall( cudaGetLastError() ); - - if (stream == 0) - cudaSafeCall ( cudaDeviceSynchronize() ); - } - - template void set(PtrStepSz mat, const uchar* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - template void set(PtrStepSz mat, const schar* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - template void set(PtrStepSz mat, const ushort* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - template void set(PtrStepSz mat, const short* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - template void set(PtrStepSz mat, const int* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - template void set(PtrStepSz mat, const float* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - template void set(PtrStepSz mat, const double* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); - - /////////////////////////////////////////////////////////////////////////// - // convert - - 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) - { - Convertor op(static_cast(alpha), static_cast(beta)); - cv::gpu::cudev::transform((PtrStepSz)src, (PtrStepSz)dst, op, WithOutMask(), stream); - } - - void convert(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_ - } - }; - - const caller_t func = tab[sdepth][ddepth]; - func(src, dst, alpha, beta, stream); - } -}}} // namespace cv { namespace gpu { namespace cudev diff --git a/modules/core/src/drawing.cpp b/modules/core/src/drawing.cpp index 0e89143c3..5cc498256 100644 --- a/modules/core/src/drawing.cpp +++ b/modules/core/src/drawing.cpp @@ -886,12 +886,14 @@ 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 there are no points, it's a zero-size polygon - if( pts.size() < 2) { + if( pts.size() == 1) { pts.assign(2,center); } } diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index b3c2b833b..a802868df 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/glob.cpp b/modules/core/src/glob.cpp index c655aa9c1..c75bd2e66 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((cv::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; } @@ -104,12 +141,24 @@ 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()); + { + 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 + status = ::GetFileAttributesExA(path.c_str(), GetFileExInfoStandard, &all_attrs); +#endif + attributes = all_attrs.dwFileAttributes; + } - return (attributes != INVALID_FILE_ATTRIBUTES) && ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); + return status && ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); #else (void)dir; struct stat stat_buf; @@ -241,4 +290,4 @@ void cv::glob(String pattern, std::vector& result, bool recursive) 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_info.cpp b/modules/core/src/gpu_info.cpp index e3400a538..5a1e56746 100644 --- a/modules/core/src/gpu_info.cpp +++ b/modules/core/src/gpu_info.cpp @@ -119,7 +119,7 @@ bool cv::gpu::deviceSupports(FeatureSet feature_set) else { DeviceInfo dev(devId); - version = dev.major() * 10 + dev.minor(); + version = dev.majorVersion() * 10 + dev.minorVersion(); if (devId < cache_size) versions[devId] = version; } @@ -455,7 +455,7 @@ size_t cv::gpu::DeviceInfo::totalConstMem() const #endif } -int cv::gpu::DeviceInfo::major() const +int cv::gpu::DeviceInfo::majorVersion() const { #ifndef HAVE_CUDA throw_no_cuda(); @@ -465,7 +465,7 @@ int cv::gpu::DeviceInfo::major() const #endif } -int cv::gpu::DeviceInfo::minor() const +int cv::gpu::DeviceInfo::minorVersion() const { #ifndef HAVE_CUDA throw_no_cuda(); @@ -908,12 +908,12 @@ bool cv::gpu::DeviceInfo::isCompatible() const return false; #else // Check PTX compatibility - if (TargetArchs::hasEqualOrLessPtx(major(), minor())) + if (TargetArchs::hasEqualOrLessPtx(majorVersion(), minorVersion())) return true; // Check BIN compatibility - for (int i = minor(); i >= 0; --i) - if (TargetArchs::hasBin(major(), i)) + for (int i = minorVersion(); i >= 0; --i) + if (TargetArchs::hasBin(majorVersion(), i)) return true; return false; diff --git a/modules/core/src/gpu_mat.cpp b/modules/core/src/gpu_mat.cpp index a2e8da65a..33a6046fe 100644 --- a/modules/core/src/gpu_mat.cpp +++ b/modules/core/src/gpu_mat.cpp @@ -46,504 +46,6 @@ using namespace cv; using namespace cv::gpu; -/////////////////////////// matrix operations ///////////////////////// - -#ifdef HAVE_CUDA - -// CUDA implementation - -#include "cuda/matrix_operations.hpp" - -namespace -{ - template void cudaSet_(GpuMat& src, Scalar s, cudaStream_t stream) - { - Scalar_ sf = s; - cudev::set(PtrStepSz(src), sf.val, src.channels(), stream); - } - - void cudaSet(GpuMat& src, Scalar s, cudaStream_t stream) - { - typedef void (*func_t)(GpuMat& src, Scalar s, cudaStream_t stream); - static const func_t funcs[] = - { - cudaSet_, - cudaSet_, - cudaSet_, - cudaSet_, - cudaSet_, - cudaSet_, - cudaSet_ - }; - - funcs[src.depth()](src, s, stream); - } - - template void cudaSet_(GpuMat& src, Scalar s, PtrStepSzb mask, cudaStream_t stream) - { - Scalar_ sf = s; - cudev::set(PtrStepSz(src), sf.val, mask, src.channels(), stream); - } - - void cudaSet(GpuMat& src, Scalar s, const GpuMat& mask, cudaStream_t stream) - { - typedef void (*func_t)(GpuMat& src, Scalar s, PtrStepSzb mask, cudaStream_t stream); - static const func_t funcs[] = - { - cudaSet_, - cudaSet_, - cudaSet_, - cudaSet_, - cudaSet_, - cudaSet_, - cudaSet_ - }; - - funcs[src.depth()](src, s, mask, stream); - } - - void cudaCopyWithMask(const GpuMat& src, GpuMat& dst, const GpuMat& mask, cudaStream_t stream) - { - cudev::copyWithMask(src.reshape(1), dst.reshape(1), src.elemSize1(), src.channels(), mask.reshape(1), mask.channels() != 1, stream); - } - - void cudaConvert(const GpuMat& src, GpuMat& dst, cudaStream_t stream) - { - cudev::convert(src.reshape(1), src.depth(), dst.reshape(1), dst.depth(), 1.0, 0.0, stream); - } - - void cudaConvert(const GpuMat& src, GpuMat& dst, double alpha, double beta, cudaStream_t stream) - { - cudev::convert(src.reshape(1), src.depth(), dst.reshape(1), dst.depth(), alpha, beta, stream); - } -} - -// NPP implementation - -namespace -{ - ////////////////////////////////////////////////////////////////////////// - // 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, cudaStream_t stream) - { - 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() ); - } - }; - template::func_ptr func> struct NppCvt - { - typedef typename NPPTypeTraits::npp_type dst_t; - - static void call(const GpuMat& src, GpuMat& dst, cudaStream_t stream) - { - 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, NPP_RND_NEAR) ); - - if (stream == 0) - 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, cudaStream_t stream) - { - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - Scalar_ nppS = s; - - NppStreamHandler h(stream); - - nppSafeCall( func(nppS.val, src.ptr(), static_cast(src.step), sz) ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; - template::func_ptr func> struct NppSet - { - typedef typename NPPTypeTraits::npp_type src_t; - - static void call(GpuMat& src, Scalar s, cudaStream_t stream) - { - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - Scalar_ nppS = s; - - NppStreamHandler h(stream); - - nppSafeCall( func(nppS[0], src.ptr(), static_cast(src.step), sz) ); - - if (stream == 0) - 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, cudaStream_t stream) - { - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - Scalar_ nppS = s; - - NppStreamHandler h(stream); - - nppSafeCall( func(nppS.val, src.ptr(), static_cast(src.step), sz, mask.ptr(), static_cast(mask.step)) ); - - if (stream == 0) - 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, cudaStream_t stream) - { - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - Scalar_ nppS = s; - - NppStreamHandler h(stream); - - nppSafeCall( func(nppS[0], src.ptr(), static_cast(src.step), sz, mask.ptr(), static_cast(mask.step)) ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; - - ////////////////////////////////////////////////////////////////////////// - // CopyMasked - - template struct NppCopyWithMaskFunc - { - 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 NppCopyWithMask - { - 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; - - NppStreamHandler h(stream); - - nppSafeCall( func(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), sz, mask.ptr(), static_cast(mask.step)) ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; -} - -// Dispatcher - -namespace -{ - void copyWithMask(const GpuMat& src, GpuMat& dst, const GpuMat& mask, cudaStream_t stream = 0) - { - CV_DbgAssert( src.size() == dst.size() && src.type() == dst.type() ); - - CV_Assert( src.depth() <= CV_64F && src.channels() <= 4 ); - CV_Assert( src.size() == mask.size() && mask.depth() == CV_8U && (mask.channels() == 1 || mask.channels() == src.channels()) ); - - if (src.depth() == CV_64F) - { - CV_Assert( deviceSupports(NATIVE_DOUBLE) ); - } - - typedef void (*func_t)(const GpuMat& src, GpuMat& dst, const GpuMat& mask, cudaStream_t stream); - static const func_t funcs[7][4] = - { - /* 8U */ {NppCopyWithMask::call, cudaCopyWithMask, NppCopyWithMask::call, NppCopyWithMask::call}, - /* 8S */ {cudaCopyWithMask , cudaCopyWithMask, cudaCopyWithMask , cudaCopyWithMask }, - /* 16U */ {NppCopyWithMask::call, cudaCopyWithMask, NppCopyWithMask::call, NppCopyWithMask::call}, - /* 16S */ {NppCopyWithMask::call, cudaCopyWithMask, NppCopyWithMask::call, NppCopyWithMask::call}, - /* 32S */ {NppCopyWithMask::call, cudaCopyWithMask, NppCopyWithMask::call, NppCopyWithMask::call}, - /* 32F */ {NppCopyWithMask::call, cudaCopyWithMask, NppCopyWithMask::call, NppCopyWithMask::call}, - /* 64F */ {cudaCopyWithMask , cudaCopyWithMask, cudaCopyWithMask , cudaCopyWithMask } - }; - - const func_t func = mask.channels() == src.channels() ? funcs[src.depth()][src.channels() - 1] : cudaCopyWithMask; - - func(src, dst, mask, stream); - } - - void convert(const GpuMat& src, GpuMat& dst, cudaStream_t stream = 0) - { - CV_DbgAssert( src.size() == dst.size() && src.channels() == dst.channels() ); - - CV_Assert( src.depth() <= CV_64F && src.channels() <= 4 ); - CV_Assert( dst.depth() <= CV_64F ); - - if (src.depth() == CV_64F || dst.depth() == CV_64F) - { - CV_Assert( deviceSupports(NATIVE_DOUBLE) ); - } - - typedef void (*func_t)(const GpuMat& src, GpuMat& dst, cudaStream_t stream); - static const func_t funcs[7][7][4] = - { - { - /* 8U -> 8U */ {0, 0, 0, 0}, - /* 8U -> 8S */ {cudaConvert , cudaConvert, cudaConvert, cudaConvert }, - /* 8U -> 16U */ {NppCvt::call, cudaConvert, cudaConvert, NppCvt::call}, - /* 8U -> 16S */ {NppCvt::call, cudaConvert, cudaConvert, NppCvt::call}, - /* 8U -> 32S */ {cudaConvert , cudaConvert, cudaConvert, cudaConvert }, - /* 8U -> 32F */ {NppCvt::call, cudaConvert, cudaConvert, cudaConvert }, - /* 8U -> 64F */ {cudaConvert , cudaConvert, cudaConvert, cudaConvert } - }, - { - /* 8S -> 8U */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 8S -> 8S */ {0,0,0,0}, - /* 8S -> 16U */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 8S -> 16S */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 8S -> 32S */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 8S -> 32F */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 8S -> 64F */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert} - }, - { - /* 16U -> 8U */ {NppCvt::call, cudaConvert, cudaConvert, NppCvt::call}, - /* 16U -> 8S */ {cudaConvert , cudaConvert, cudaConvert, cudaConvert }, - /* 16U -> 16U */ {0,0,0,0}, - /* 16U -> 16S */ {cudaConvert , cudaConvert, cudaConvert, cudaConvert }, - /* 16U -> 32S */ {NppCvt::call, cudaConvert, cudaConvert, cudaConvert }, - /* 16U -> 32F */ {NppCvt::call, cudaConvert, cudaConvert, cudaConvert }, - /* 16U -> 64F */ {cudaConvert , cudaConvert, cudaConvert, cudaConvert } - }, - { - /* 16S -> 8U */ {NppCvt::call, cudaConvert, cudaConvert, NppCvt::call}, - /* 16S -> 8S */ {cudaConvert , cudaConvert, cudaConvert, cudaConvert }, - /* 16S -> 16U */ {cudaConvert , cudaConvert, cudaConvert, cudaConvert }, - /* 16S -> 16S */ {0,0,0,0}, - /* 16S -> 32S */ {NppCvt::call, cudaConvert, cudaConvert, cudaConvert }, - /* 16S -> 32F */ {NppCvt::call, cudaConvert, cudaConvert, cudaConvert }, - /* 16S -> 64F */ {cudaConvert , cudaConvert, cudaConvert, cudaConvert } - }, - { - /* 32S -> 8U */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 32S -> 8S */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 32S -> 16U */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 32S -> 16S */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 32S -> 32S */ {0,0,0,0}, - /* 32S -> 32F */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 32S -> 64F */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert} - }, - { - /* 32F -> 8U */ {NppCvt::call, cudaConvert, cudaConvert, cudaConvert}, - /* 32F -> 8S */ {cudaConvert , cudaConvert, cudaConvert, cudaConvert}, - /* 32F -> 16U */ {NppCvt::call, cudaConvert, cudaConvert, cudaConvert}, - /* 32F -> 16S */ {NppCvt::call, cudaConvert, cudaConvert, cudaConvert}, - /* 32F -> 32S */ {cudaConvert , cudaConvert, cudaConvert, cudaConvert}, - /* 32F -> 32F */ {0,0,0,0}, - /* 32F -> 64F */ {cudaConvert , cudaConvert, cudaConvert, cudaConvert} - }, - { - /* 64F -> 8U */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 64F -> 8S */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 64F -> 16U */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 64F -> 16S */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 64F -> 32S */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 64F -> 32F */ {cudaConvert, cudaConvert, cudaConvert, cudaConvert}, - /* 64F -> 64F */ {0,0,0,0} - } - }; - - const bool aligned = isAligned(src.data, 16) && isAligned(dst.data, 16); - if (!aligned) - { - cudaConvert(src, dst, stream); - return; - } - - const func_t func = funcs[src.depth()][dst.depth()][src.channels() - 1]; - CV_DbgAssert( func != 0 ); - - func(src, dst, stream); - } - - void convert(const GpuMat& src, GpuMat& dst, double alpha, double beta, cudaStream_t stream = 0) - { - CV_DbgAssert( src.size() == dst.size() && src.channels() == dst.channels() ); - - CV_Assert( src.depth() <= CV_64F && src.channels() <= 4 ); - CV_Assert( dst.depth() <= CV_64F ); - - if (src.depth() == CV_64F || dst.depth() == CV_64F) - { - CV_Assert( deviceSupports(NATIVE_DOUBLE) ); - } - - cudaConvert(src, dst, alpha, beta, stream); - } - - void set(GpuMat& m, Scalar s, cudaStream_t stream = 0) - { - if (s[0] == 0.0 && s[1] == 0.0 && s[2] == 0.0 && s[3] == 0.0) - { - if (stream) - cudaSafeCall( cudaMemset2DAsync(m.data, m.step, 0, m.cols * m.elemSize(), m.rows, stream) ); - else - 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]); - if (stream) - cudaSafeCall( cudaMemset2DAsync(m.data, m.step, val, m.cols * m.elemSize(), m.rows, stream) ); - else - cudaSafeCall( cudaMemset2D(m.data, m.step, val, m.cols * m.elemSize(), m.rows) ); - return; - } - } - - typedef void (*func_t)(GpuMat& src, Scalar s, cudaStream_t stream); - static const func_t funcs[7][4] = - { - {NppSet::call, cudaSet , cudaSet , NppSet::call}, - {NppSet::call, NppSet::call, NppSet::call, NppSet::call}, - {NppSet::call, NppSet::call, cudaSet , NppSet::call}, - {NppSet::call, NppSet::call, cudaSet , NppSet::call}, - {NppSet::call, cudaSet , cudaSet , NppSet::call}, - {NppSet::call, cudaSet , cudaSet , NppSet::call}, - {cudaSet , cudaSet , cudaSet , cudaSet } - }; - - CV_Assert( m.depth() <= CV_64F && m.channels() <= 4 ); - - if (m.depth() == CV_64F) - { - CV_Assert( deviceSupports(NATIVE_DOUBLE) ); - } - - funcs[m.depth()][m.channels() - 1](m, s, stream); - } - - void set(GpuMat& m, Scalar s, const GpuMat& mask, cudaStream_t stream = 0) - { - CV_DbgAssert( !mask.empty() ); - - CV_Assert( m.depth() <= CV_64F && m.channels() <= 4 ); - - if (m.depth() == CV_64F) - { - CV_Assert( deviceSupports(NATIVE_DOUBLE) ); - } - - typedef void (*func_t)(GpuMat& src, Scalar s, const GpuMat& mask, cudaStream_t stream); - static const func_t funcs[7][4] = - { - {NppSetMask::call, cudaSet, cudaSet, NppSetMask::call}, - {cudaSet , cudaSet, cudaSet, cudaSet }, - {NppSetMask::call, cudaSet, cudaSet, NppSetMask::call}, - {NppSetMask::call, cudaSet, cudaSet, NppSetMask::call}, - {NppSetMask::call, cudaSet, cudaSet, NppSetMask::call}, - {NppSetMask::call, cudaSet, cudaSet, NppSetMask::call}, - {cudaSet , cudaSet, cudaSet, cudaSet } - }; - - funcs[m.depth()][m.channels() - 1](m, s, mask, stream); - } -} - -#endif // HAVE_CUDA - 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), @@ -651,288 +153,6 @@ cv::gpu::GpuMat::GpuMat(const GpuMat& m, Rect roi) : rows = cols = 0; } -void cv::gpu::GpuMat::create(int _rows, int _cols, int _type) -{ -#ifndef HAVE_CUDA - (void) _rows; - (void) _cols; - (void) _type; - throw_no_cuda(); -#else - _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 + _type; - rows = _rows; - cols = _cols; - - size_t esz = elemSize(); - - void* devPtr; - - if (rows > 1 && cols > 1) - { - cudaSafeCall( cudaMallocPitch(&devPtr, &step, esz * cols, rows) ); - } - else - { - // Single row or single column must be continuous - cudaSafeCall( 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; - } -#endif -} - -void cv::gpu::GpuMat::release() -{ -#ifdef HAVE_CUDA - if (refcount && CV_XADD(refcount, -1) == 1) - { - cudaFree(datastart); - fastFree(refcount); - } - - data = datastart = dataend = 0; - step = rows = cols = 0; - refcount = 0; -#endif -} - -void cv::gpu::GpuMat::upload(InputArray arr) -{ -#ifndef HAVE_CUDA - (void) arr; - throw_no_cuda(); -#else - Mat mat = arr.getMat(); - - CV_DbgAssert( !mat.empty() ); - - create(mat.size(), mat.type()); - - cudaSafeCall( cudaMemcpy2D(data, step, mat.data, mat.step, cols * elemSize(), rows, cudaMemcpyHostToDevice) ); -#endif -} - -void cv::gpu::GpuMat::upload(InputArray arr, Stream& _stream) -{ -#ifndef HAVE_CUDA - (void) arr; - (void) _stream; - throw_no_cuda(); -#else - Mat mat = arr.getMat(); - - CV_DbgAssert( !mat.empty() ); - - create(mat.size(), mat.type()); - - cudaStream_t stream = StreamAccessor::getStream(_stream); - cudaSafeCall( cudaMemcpy2DAsync(data, step, mat.data, mat.step, cols * elemSize(), rows, cudaMemcpyHostToDevice, stream) ); -#endif -} - -void cv::gpu::GpuMat::download(OutputArray _dst) const -{ -#ifndef HAVE_CUDA - (void) _dst; - throw_no_cuda(); -#else - CV_DbgAssert( !empty() ); - - _dst.create(size(), type()); - Mat dst = _dst.getMat(); - - cudaSafeCall( cudaMemcpy2D(dst.data, dst.step, data, step, cols * elemSize(), rows, cudaMemcpyDeviceToHost) ); -#endif -} - -void cv::gpu::GpuMat::download(OutputArray _dst, Stream& _stream) const -{ -#ifndef HAVE_CUDA - (void) _dst; - (void) _stream; - throw_no_cuda(); -#else - CV_DbgAssert( !empty() ); - - _dst.create(size(), type()); - Mat dst = _dst.getMat(); - - cudaStream_t stream = StreamAccessor::getStream(_stream); - cudaSafeCall( cudaMemcpy2DAsync(dst.data, dst.step, data, step, cols * elemSize(), rows, cudaMemcpyDeviceToHost, stream) ); -#endif -} - -void cv::gpu::GpuMat::copyTo(OutputArray _dst) const -{ -#ifndef HAVE_CUDA - (void) _dst; - throw_no_cuda(); -#else - CV_DbgAssert( !empty() ); - - _dst.create(size(), type()); - GpuMat dst = _dst.getGpuMat(); - - cudaSafeCall( cudaMemcpy2D(dst.data, dst.step, data, step, cols * elemSize(), rows, cudaMemcpyDeviceToDevice) ); -#endif -} - -void cv::gpu::GpuMat::copyTo(OutputArray _dst, Stream& _stream) const -{ -#ifndef HAVE_CUDA - (void) _dst; - (void) _stream; - throw_no_cuda(); -#else - CV_DbgAssert( !empty() ); - - _dst.create(size(), type()); - GpuMat dst = _dst.getGpuMat(); - - cudaStream_t stream = StreamAccessor::getStream(_stream); - cudaSafeCall( cudaMemcpy2DAsync(dst.data, dst.step, data, step, cols * elemSize(), rows, cudaMemcpyDeviceToDevice, stream) ); -#endif -} - -void cv::gpu::GpuMat::copyTo(OutputArray _dst, InputArray _mask, Stream& _stream) const -{ -#ifndef HAVE_CUDA - (void) _dst; - (void) _mask; - (void) _stream; - throw_no_cuda(); -#else - CV_DbgAssert( !empty() ); - - _dst.create(size(), type()); - GpuMat dst = _dst.getGpuMat(); - - GpuMat mask = _mask.getGpuMat(); - - cudaStream_t stream = StreamAccessor::getStream(_stream); - ::copyWithMask(*this, dst, mask, stream); -#endif -} - -GpuMat& cv::gpu::GpuMat::setTo(Scalar s, Stream& _stream) -{ -#ifndef HAVE_CUDA - (void) s; - (void) _stream; - throw_no_cuda(); -#else - CV_DbgAssert( !empty() ); - - cudaStream_t stream = StreamAccessor::getStream(_stream); - ::set(*this, s, stream); -#endif - - return *this; -} - -GpuMat& cv::gpu::GpuMat::setTo(Scalar s, InputArray _mask, Stream& _stream) -{ -#ifndef HAVE_CUDA - (void) s; - (void) _mask; - (void) _stream; - throw_no_cuda(); -#else - CV_DbgAssert( !empty() ); - - GpuMat mask = _mask.getGpuMat(); - - cudaStream_t stream = StreamAccessor::getStream(_stream); - ::set(*this, s, mask, stream); -#endif - - return *this; -} - -void cv::gpu::GpuMat::convertTo(OutputArray _dst, int rtype, Stream& _stream) const -{ -#ifndef HAVE_CUDA - (void) _dst; - (void) rtype; - (void) _stream; - throw_no_cuda(); -#else - 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); - if (sdepth == ddepth) - { - if (_stream) - copyTo(_dst, _stream); - else - copyTo(_dst); - - return; - } - - GpuMat src = *this; - - _dst.create(size(), rtype); - GpuMat dst = _dst.getGpuMat(); - - cudaStream_t stream = StreamAccessor::getStream(_stream); - ::convert(src, dst, stream); -#endif -} - -void cv::gpu::GpuMat::convertTo(OutputArray _dst, int rtype, double alpha, double beta, Stream& _stream) const -{ -#ifndef HAVE_CUDA - (void) _dst; - (void) rtype; - (void) alpha; - (void) beta; - (void) _stream; - throw_no_cuda(); -#else - if (rtype < 0) - rtype = type(); - else - rtype = CV_MAKETYPE(CV_MAT_DEPTH(rtype), channels()); - - GpuMat src = *this; - - _dst.create(size(), rtype); - GpuMat dst = _dst.getGpuMat(); - - cudaStream_t stream = StreamAccessor::getStream(_stream); - ::convert(src, dst, alpha, beta, stream); -#endif -} - GpuMat cv::gpu::GpuMat::reshape(int new_cn, int new_rows) const { GpuMat hdr = *this; @@ -1124,3 +344,101 @@ GpuMat cv::gpu::allocMatFromBuf(int rows, int cols, int type, GpuMat& mat) 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 index 879775355..fcdf480a9 100644 --- a/modules/core/src/gpu_stream.cpp +++ b/modules/core/src/gpu_stream.cpp @@ -100,7 +100,7 @@ cv::gpu::Stream::Stream() #ifndef HAVE_CUDA throw_no_cuda(); #else - impl_ = new Impl; + impl_ = makePtr(); #endif } @@ -182,7 +182,7 @@ void cv::gpu::Stream::enqueueHostCallback(StreamCallback callback, void* userDat Stream& cv::gpu::Stream::Null() { - static Stream s(new Impl(0)); + static Stream s(Ptr(new Impl(0))); return s; } @@ -195,10 +195,6 @@ cv::gpu::Stream::operator bool_type() const #endif } -template <> void cv::Ptr::delete_obj() -{ - if (obj) delete obj; -} //////////////////////////////////////////////////////////////// // Stream @@ -249,7 +245,7 @@ cv::gpu::Event::Event(CreateFlags flags) (void) flags; throw_no_cuda(); #else - impl_ = new Impl(flags); + impl_ = makePtr(flags); #endif } @@ -301,8 +297,3 @@ float cv::gpu::Event::elapsedTime(const Event& start, const Event& end) return ms; #endif } - -template <> void cv::Ptr::delete_obj() -{ - if (obj) delete obj; -} diff --git a/modules/core/src/lapack.cpp b/modules/core/src/lapack.cpp index 9e64697c3..f6bc7c88c 100644 --- a/modules/core/src/lapack.cpp +++ b/modules/core/src/lapack.cpp @@ -1823,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/matmul.cpp b/modules/core/src/matmul.cpp index 404c5b434..7d832cb0f 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}; @@ -2761,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() ) @@ -2896,6 +2911,27 @@ 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) { diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 053dd1cef..d2032b2e5 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -995,6 +995,11 @@ Mat _InputArray::getMat(int i) const return !v.empty() ? Mat(size(i), t, (void*)&v[0]) : 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; @@ -1100,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 ) { @@ -1224,6 +1234,11 @@ Size _InputArray::size(int i) const 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 ) { @@ -1338,6 +1353,11 @@ bool _InputArray::empty() const if( k == OPENGL_BUFFER ) return ((const ogl::Buffer*)obj)->empty(); + if( k == OCL_MAT ) + { + CV_Error(CV_StsNotImplemented, "This method is not implemented for oclMat yet"); + } + if( k == GPU_MAT ) return ((const gpu::GpuMat*)obj)->empty(); @@ -1573,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" ); @@ -1684,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 ) { diff --git a/modules/core/src/opengl.cpp b/modules/core/src/opengl.cpp index f8a647e8e..36a437a2d 100644 --- a/modules/core/src/opengl.cpp +++ b/modules/core/src/opengl.cpp @@ -484,7 +484,7 @@ cv::ogl::Buffer::Buffer(int arows, int acols, int atype, unsigned int abufId, bo (void) autoRelease; throw_no_ogl(); #else - impl_ = new Impl(abufId, autoRelease); + impl_.reset(new Impl(abufId, autoRelease)); rows_ = arows; cols_ = acols; type_ = atype; @@ -500,7 +500,7 @@ cv::ogl::Buffer::Buffer(Size asize, int atype, unsigned int abufId, bool autoRel (void) autoRelease; throw_no_ogl(); #else - impl_ = new Impl(abufId, autoRelease); + impl_.reset(new Impl(abufId, autoRelease)); rows_ = asize.height; cols_ = asize.width; type_ = atype; @@ -529,7 +529,7 @@ cv::ogl::Buffer::Buffer(InputArray arr, Target target, bool autoRelease) : rows_ 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(); @@ -552,7 +552,7 @@ void cv::ogl::Buffer::create(int arows, int acols, int atype, Target target, boo 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; @@ -563,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; @@ -836,10 +836,6 @@ unsigned int cv::ogl::Buffer::bufId() const #endif } -template <> void cv::Ptr::delete_obj() -{ - if (obj) delete obj; -} ////////////////////////////////////////////////////////////////////////////////////////// // ogl::Texture @@ -972,7 +968,7 @@ cv::ogl::Texture2D::Texture2D(int arows, int acols, Format aformat, unsigned int (void) autoRelease; throw_no_ogl(); #else - impl_ = new Impl(atexId, autoRelease); + impl_.reset(new Impl(atexId, autoRelease)); rows_ = arows; cols_ = acols; format_ = aformat; @@ -988,7 +984,7 @@ cv::ogl::Texture2D::Texture2D(Size asize, Format aformat, unsigned int atexId, b (void) autoRelease; throw_no_ogl(); #else - impl_ = new Impl(atexId, autoRelease); + impl_.reset(new Impl(atexId, autoRelease)); rows_ = asize.height; cols_ = asize.width; format_ = aformat; @@ -1028,7 +1024,7 @@ 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; } @@ -1041,7 +1037,7 @@ cv::ogl::Texture2D::Texture2D(InputArray arr, bool autoRelease) : rows_(0), cols 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 @@ -1053,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; } } @@ -1076,7 +1072,7 @@ void cv::ogl::Texture2D::create(int arows, int acols, Format aformat, bool autoR 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; @@ -1087,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; @@ -1243,10 +1239,6 @@ unsigned int cv::ogl::Texture2D::texId() const #endif } -template <> void cv::Ptr::delete_obj() -{ - if (obj) delete obj; -} //////////////////////////////////////////////////////////////////////// // ogl::Arrays diff --git a/modules/core/src/out.cpp b/modules/core/src/out.cpp index cc2294ded..3ed454ebf 100644 --- a/modules/core/src/out.cpp +++ b/modules/core/src/out.cpp @@ -256,7 +256,7 @@ namespace cv::Ptr format(const cv::Mat& mtx) const { char braces[5] = {'\0', '\0', ';', '\0', '\0'}; - return new FormattedImpl("[", "]", mtx, braces, + return cv::makePtr("[", "]", mtx, &*braces, mtx.cols == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f ); } }; @@ -270,7 +270,7 @@ namespace char braces[5] = {'[', ']', '\0', '[', ']'}; if (mtx.cols == 1) braces[0] = braces[1] = '\0'; - return new FormattedImpl("[", "]", mtx, braces, + return cv::makePtr("[", "]", mtx, &*braces, mtx.cols*mtx.channels() == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f ); } }; @@ -288,7 +288,8 @@ namespace char braces[5] = {'[', ']', '\0', '[', ']'}; if (mtx.cols == 1) braces[0] = braces[1] = '\0'; - return new FormattedImpl("array([", cv::format("], type='%s')", numpyTypes[mtx.depth()]), mtx, braces, + 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 ); } }; @@ -300,7 +301,8 @@ namespace cv::Ptr format(const cv::Mat& mtx) const { char braces[5] = {'\0', '\0', '\0', '\0', '\0'}; - return new FormattedImpl(cv::String(), mtx.rows > 1 ? cv::String("\n") : cv::String(), mtx, braces, + 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 ); } }; @@ -312,7 +314,7 @@ namespace cv::Ptr format(const cv::Mat& mtx) const { char braces[5] = {'\0', '\0', ',', '\0', '\0'}; - return new FormattedImpl("{", "}", mtx, braces, + return cv::makePtr("{", "}", mtx, &*braces, mtx.cols == 1 || !multiline, mtx.depth() == CV_64F ? prec64f : prec32f ); } }; @@ -330,16 +332,16 @@ namespace cv switch(fmt) { case FMT_MATLAB: - return new MatlabFormatter(); + return makePtr(); case FMT_CSV: - return new CSVFormatter(); + return makePtr(); case FMT_PYTHON: - return new PythonFormatter(); + return makePtr(); case FMT_NUMPY: - return new NumpyFormatter(); + return makePtr(); case FMT_C: - return new CFormatter(); + return makePtr(); } - return new MatlabFormatter(); + return makePtr(); } } // cv diff --git a/modules/core/src/parallel.cpp b/modules/core/src/parallel.cpp index 0b2a845ac..27d7ecc03 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 657d86a16..39ce63313 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 @@ -5130,9 +5129,11 @@ FileStorage::FileStorage(const String& filename, int flags, const String& encodi 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; } @@ -5148,8 +5149,8 @@ FileStorage::~FileStorage() 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; @@ -5157,7 +5158,7 @@ bool FileStorage::open(const String& filename, int flags, const String& encoding bool FileStorage::isOpened() const { - return !fs.empty() && fs.obj->is_opened; + return fs && fs->is_opened; } void FileStorage::release() @@ -5170,8 +5171,8 @@ void FileStorage::release() String FileStorage::releaseAndGetString() { String buf; - if( fs.obj && fs.obj->outbuf ) - icvClose(fs.obj, &buf); + if( fs && fs->outbuf ) + icvClose(fs, &buf); release(); return buf; @@ -5480,7 +5481,7 @@ void write( FileStorage& fs, const String& name, const Mat& value ) // TODO: the 4 functions below need to be implemented more efficiently void write( FileStorage& fs, const String& name, const SparseMat& value ) { - Ptr mat = cvCreateSparseMat(value); + Ptr mat(cvCreateSparseMat(value)); cvWrite( *fs, name.size() ? name.c_str() : 0, mat ); } @@ -5530,8 +5531,8 @@ 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)); + Ptr m((CvSparseMat*)cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node)); + CV_Assert(CV_IS_SPARSE_MAT(m)); m->copyToSparseMat(mat); } diff --git a/modules/core/src/rand.cpp b/modules/core/src/rand.cpp index 079e1fb7b..ffce63484 100644 --- a/modules/core/src/rand.cpp +++ b/modules/core/src/rand.cpp @@ -728,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; diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 3b8916bbf..86555fcc3 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -200,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 ) @@ -272,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 ) @@ -428,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]; +} } @@ -440,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 ); @@ -492,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 ); @@ -513,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 ); @@ -572,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 ); @@ -746,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) { @@ -786,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}; @@ -1251,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]; +} } @@ -1300,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; @@ -1371,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}; @@ -1438,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(); @@ -1449,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(); @@ -1512,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}; diff --git a/modules/core/src/stl.cpp b/modules/core/src/stl.cpp index 09ba66c21..f03c1a2d7 100644 --- a/modules/core/src/stl.cpp +++ b/modules/core/src/stl.cpp @@ -66,4 +66,4 @@ void cv::String::deallocate() { cv::fastFree(data-1); } -} \ No newline at end of file +} diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index b828435b7..738e863d7 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 @@ -371,12 +404,39 @@ String format( const char* fmt, ... ) 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"); 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) { @@ -389,6 +449,7 @@ String tempfile( const char* suffix ) DeleteFileA(temp_file); fname = temp_file; +#endif # else # ifdef ANDROID //char defaultTemplate[] = "/mnt/sdcard/__opencv_temp.XXXXXX"; @@ -486,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 ); @@ -677,7 +704,11 @@ cvErrorFromIppStatus( int status ) } -#if defined BUILD_SHARED_LIBS && defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE +#if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE +#ifdef HAVE_WINRT + #pragma warning(disable:4447) // Disable warning 'main' signature found without threading model +#endif + BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID ); BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID ) @@ -698,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); } @@ -791,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 index 4dbb06f31..89e004265 100644 --- a/modules/core/src/types.cpp +++ b/modules/core/src/types.cpp @@ -136,4 +136,4 @@ float KeyPoint::overlap( const KeyPoint& kp1, const KeyPoint& kp2 ) return ovrl; } -} // cv \ No newline at end of file +} // cv diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index 721fd0e6b..7486e134a 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -1123,7 +1123,7 @@ struct MeanOp : public BaseElemWiseOp } double getMaxErr(int) { - return 1e-6; + return 1e-5; } }; diff --git a/modules/core/test/test_ds.cpp b/modules/core/test/test_ds.cpp index d79786054..c71deed06 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 16025fa8f..1c0c7b00b 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_io.cpp b/modules/core/test/test_io.cpp index 602dcd1e1..ba6656761 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -270,16 +270,16 @@ protected: cvRelease((void**)&m_nd); - Ptr m_s = (CvSparseMat*)fs["test_sparse_mat"].readObj(); - Ptr _test_sparse_ = cvCreateSparseMat(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 = cvCreateSparseMat(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 ); @@ -391,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); @@ -399,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(...) { diff --git a/modules/core/test/test_main.cpp b/modules/core/test/test_main.cpp index 6b2499344..d5400e20f 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 245347b8b..3c8ae8bf9 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -510,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 ); + } } }; @@ -643,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 || @@ -736,7 +762,7 @@ void Core_ArrayOpTest::run( int /* start_from */) } } - Ptr M2 = cvCreateSparseMat(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 b9beeb7d3..377742386 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -2755,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 6b36883cf..8d3341e59 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 5956e13e3..000000000 --- a/modules/core/test/test_precomp.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "test_precomp.hpp" diff --git a/modules/core/test/test_ptr.cpp b/modules/core/test/test_ptr.cpp new file mode 100644 index 000000000..c6f793ab1 --- /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 000000000..3c7b0592c --- /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 000000000..63bfc9569 --- /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 000000000..385e1713e --- /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 000000000..02803b003 --- /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 000000000..edbe8a586 --- /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 000000000..9f9ba6000 --- /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 000000000..4c9022631 --- /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/cudev/include/opencv2/cudev/block/scan.hpp b/modules/cudev/include/opencv2/cudev/block/scan.hpp new file mode 100644 index 000000000..c54dfef9f --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/block/scan.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_BLOCK_SCAN_HPP__ +#define __OPENCV_CUDEV_BLOCK_SCAN_HPP__ + +#include "../common.hpp" +#include "../warp/scan.hpp" + +namespace cv { namespace cudev { + +template +__device__ T blockScanInclusive(T data, volatile T* smem, uint tid) +{ + if (THREADS_NUM > WARP_SIZE) + { + // 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)) + { + smem[tid >> LOG_WARP_SIZE] = warpResult; + } + + __syncthreads(); + + if (tid < (THREADS_NUM / WARP_SIZE)) + { + // grab top warp elements + T val = smem[tid]; + + // calculate exclusive scan and write back to shared memory + smem[tid] = warpScanExclusive(val, smem, tid); + } + + __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 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 000000000..c48e9146e --- /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/cudev/include/opencv2/cudev/common.hpp b/modules/cudev/include/opencv2/cudev/common.hpp new file mode 100644 index 000000000..be7990172 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/common.hpp @@ -0,0 +1,93 @@ +/*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_COMMON_HPP__ +#define __OPENCV_CUDEV_COMMON_HPP__ + +#include +#include "opencv2/core/gpu.hpp" +#include "opencv2/core/gpu_stream_accessor.hpp" + +namespace cv { namespace cudev { + +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) +{ + if (cudaSuccess != err) + cv::error(cv::Error::GpuApiCallError, cudaGetErrorString(err), func, file, line); +} + +#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 + +// divUp + +__host__ __device__ __forceinline__ int divUp(int total, int grain) +{ + return (total + grain - 1) / grain; +} + +// math constants + +#define CV_PI_F ((float)CV_PI) +#define CV_LOG2_F ((float)CV_LOG2) + +}} + +#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 000000000..f35ea2dc3 --- /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 000000000..f7e965572 --- /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 000000000..13f07c15a --- /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/cudev/include/opencv2/cudev/expr/deriv.hpp b/modules/cudev/include/opencv2/cudev/expr/deriv.hpp new file mode 100644 index 000000000..822a86b9a --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/expr/deriv.hpp @@ -0,0 +1,121 @@ +/*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_DERIV_HPP__ +#define __OPENCV_CUDEV_EXPR_DERIV_HPP__ + +#include "../common.hpp" +#include "../ptr2d/traits.hpp" +#include "../ptr2d/deriv.hpp" +#include "expr.hpp" + +namespace cv { namespace cudev { + +// derivX + +template +__host__ Expr::ptr_type> > +derivX_(const SrcPtr& src) +{ + return makeExpr(derivXPtr(src)); +} + +// derivY + +template +__host__ Expr::ptr_type> > +derivY_(const SrcPtr& src) +{ + return makeExpr(derivYPtr(src)); +} + +// 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)); +} + +}} + +#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 000000000..46c780b4a --- /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 000000000..56a067de9 --- /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 000000000..0fdde02e5 --- /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 000000000..a30f6a6f3 --- /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 000000000..905013e42 --- /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 000000000..f942a3fb6 --- /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 000000000..8be854780 --- /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 000000000..9b20fcc2c --- /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 000000000..3ac532819 --- /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 000000000..d3a40db0e --- /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 000000000..d7d3ea834 --- /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 000000000..707b842f9 --- /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 000000000..c9d715982 --- /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/cudev/include/opencv2/cudev/grid/detail/histogram.hpp b/modules/cudev/include/opencv2/cudev/grid/detail/histogram.hpp new file mode 100644 index 000000000..a27955d5d --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/detail/histogram.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_GRID_HISTOGRAM_DETAIL_HPP__ +#define __OPENCV_CUDEV_GRID_HISTOGRAM_DETAIL_HPP__ + +#include "../../common.hpp" +#include "../../util/atomic.hpp" + +namespace cv { namespace cudev { + +namespace grid_histogram_detail +{ + template + __global__ void histogram(const SrcPtr src, ResType* hist, const MaskPtr mask, const int rows, const int cols) + { + #if CV_CUDEV_ARCH >= 120 + __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) + { + for (int x = threadIdx.x; x < cols; x += blockDim.x) + { + if (mask(y, x)) + { + const uint data = src(y, x); + atomicAdd(&smem[data % BIN_COUNT], 1); + } + } + } + + __syncthreads(); + + for (int i = tid; i < BIN_COUNT; i += BLOCK_SIZE) + { + const ResType histVal = smem[i]; + if (histVal > 0) + atomicAdd(hist + i, histVal); + } + #endif + } + + 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 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 000000000..b06d7ddbb --- /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 000000000..b14792cf4 --- /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 000000000..16c8b2091 --- /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 000000000..b257e7503 --- /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 000000000..154004f6e --- /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 000000000..0bd76ac46 --- /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 000000000..0e0df0794 --- /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 000000000..3854a1740 --- /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 000000000..8d3e0826d --- /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 000000000..ecb1a19c8 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/grid/histogram.hpp @@ -0,0 +1,119 @@ +/*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()) +{ + CV_Assert( deviceSupports(SHARED_ATOMICS) ); + + 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()) +{ + CV_Assert( deviceSupports(SHARED_ATOMICS) ); + + 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 000000000..d948c1267 --- /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 000000000..99833bd3f --- /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 000000000..f9e351242 --- /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 000000000..78584aad8 --- /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 000000000..0da5e2d8a --- /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/core/src/cuda/matrix_operations.hpp b/modules/cudev/include/opencv2/cudev/grid/transpose.hpp similarity index 80% rename from modules/core/src/cuda/matrix_operations.hpp rename to modules/cudev/include/opencv2/cudev/grid/transpose.hpp index 4e451061b..5e8f24868 100644 --- a/modules/core/src/cuda/matrix_operations.hpp +++ b/modules/cudev/include/opencv2/cudev/grid/transpose.hpp @@ -41,17 +41,29 @@ // //M*/ -#include "opencv2/core/cuda/common.hpp" +#pragma once -namespace cv { namespace gpu { namespace cudev +#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()) { - void copyWithMask(PtrStepSzb src, PtrStepSzb dst, size_t elemSize1, int cn, PtrStepSzb mask, bool multiChannelMask, cudaStream_t stream); + const int rows = getRows(src); + const int cols = getCols(src); - template - void set(PtrStepSz mat, const T* scalar, int channels, cudaStream_t stream); + dst.create(cols, rows); - template - void set(PtrStepSz mat, const T* scalar, PtrStepSzb mask, int channels, cudaStream_t stream); + transpose_detail::transpose(shrinkPtr(src), shrinkPtr(dst), rows, cols, StreamAccessor::getStream(stream)); +} - void convert(PtrStepSzb src, int sdepth, PtrStepSzb dst, int ddepth, double alpha, double beta, cudaStream_t stream); -}}} +}} + +#endif diff --git a/modules/cudev/include/opencv2/cudev/ptr2d/constant.hpp b/modules/cudev/include/opencv2/cudev/ptr2d/constant.hpp new file mode 100644 index 000000000..d3c56e771 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/constant.hpp @@ -0,0 +1,93 @@ +/*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_CONSTANT_HPP__ +#define __OPENCV_CUDEV_PTR2D_CONSTANT_HPP__ + +#include "../common.hpp" +#include "traits.hpp" + +namespace cv { namespace cudev { + +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; +} + +template ConstantPtrSz +__host__ constantPtr(T value, int rows, int cols) +{ + ConstantPtrSz p; + p.value = value; + p.rows = rows; + p.cols = cols; + return p; +} + +template struct PtrTraits< ConstantPtrSz > : PtrTraitsBase< ConstantPtrSz, ConstantPtr > +{ +}; + +}} + +#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 000000000..097007400 --- /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 000000000..e378c5237 --- /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 000000000..c90e79174 --- /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 000000000..7304a8c7f --- /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 000000000..50bb0874f --- /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 000000000..e86d7191e --- /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 000000000..e47719c6e --- /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 000000000..1ff337193 --- /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 000000000..db2669a40 --- /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 000000000..10a4bad90 --- /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 000000000..095864fcb --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/ptr2d/texture.hpp @@ -0,0 +1,176 @@ +/*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 +{ + template struct CvCudevTextureRef + { + typedef texture TexRef; + + static TexRef ref; + + __host__ static void bind(const cv::cudev::GlobPtrSz& mat, + bool normalizedCoords = false, + cudaTextureFilterMode filterMode = cudaFilterModePoint, + cudaTextureAddressMode addressMode = cudaAddressModeClamp) + { + ref.normalized = normalizedCoords; + ref.filterMode = filterMode; + ref.addressMode[0] = addressMode; + ref.addressMode[1] = addressMode; + ref.addressMode[2] = addressMode; + + cudaChannelFormatDesc desc = cudaCreateChannelDesc(); + + CV_CUDEV_SAFE_CALL( cudaBindTexture2D(0, &ref, mat.data, &desc, mat.cols, mat.rows, mat.step) ); + } + + __host__ static void unbind() + { + CV_CUDEV_SAFE_CALL( cudaUnbindTexture(ref) ); + } + }; + + template + typename CvCudevTextureRef::TexRef CvCudevTextureRef::ref; +} + +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 + { + #if CV_CUDEV_ARCH < 300 + // Use the texture reference + return tex2D(CvCudevTextureRef::ref, x, y); + #else + // Use the texture object + return tex2D(texObj, x, y); + #endif + } +}; + +template struct Texture : TexturePtr +{ + int rows, cols; + bool cc30; + + __host__ explicit Texture(const GlobPtrSz& mat, + bool normalizedCoords = false, + cudaTextureFilterMode filterMode = cudaFilterModePoint, + cudaTextureAddressMode addressMode = cudaAddressModeClamp) + { + cc30 = deviceSupports(FEATURE_SET_COMPUTE_30); + + rows = mat.rows; + cols = mat.cols; + + if (cc30) + { + // Use the texture object + 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.normalizedCoords = normalizedCoords; + texDescr.filterMode = filterMode; + texDescr.addressMode[0] = addressMode; + texDescr.addressMode[1] = addressMode; + texDescr.addressMode[2] = addressMode; + texDescr.readMode = cudaReadModeElementType; + + CV_CUDEV_SAFE_CALL( cudaCreateTextureObject(&this->texObj, &texRes, &texDescr, 0) ); + } + else + { + // Use the texture reference + CvCudevTextureRef::bind(mat, normalizedCoords, filterMode, addressMode); + } + } + + __host__ ~Texture() + { + if (cc30) + { + // Use the texture object + cudaDestroyTextureObject(this->texObj); + } + else + { + // Use the texture reference + CvCudevTextureRef::unbind(); + } + } +}; + +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 000000000..7fb4b32b1 --- /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 000000000..f540e7521 --- /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 000000000..80e5fbeef --- /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 000000000..934939f62 --- /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 000000000..2da110231 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/util/atomic.hpp @@ -0,0 +1,197 @@ +/*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) +{ +#if CV_CUDEV_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 +} + +__device__ static double atomicAdd(double* address, double val) +{ +#if CV_CUDEV_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 +} + +// 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) +{ +#if CV_CUDEV_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 +} + +__device__ static double atomicMin(double* address, double val) +{ +#if CV_CUDEV_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 +} + +// 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) +{ +#if CV_CUDEV_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 +} + +__device__ static double atomicMax(double* address, double val) +{ +#if CV_CUDEV_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 +} + +}} + +#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 000000000..2fc84946b --- /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 000000000..d71164283 --- /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 000000000..58faca6b5 --- /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 000000000..ff7ce8598 --- /dev/null +++ b/modules/cudev/include/opencv2/cudev/util/saturate_cast.hpp @@ -0,0 +1,272 @@ +/*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) +{ +#if CV_CUDEV_ARCH >= 130 + return __double2int_rn(v); +#else + return saturate_cast((float) v); +#endif +} + +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) +{ +#if CV_CUDEV_ARCH >= 130 + return __double2uint_rn(v); +#else + return saturate_cast((float) v); +#endif +} + +}} + +#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 000000000..db63f5180 --- /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 000000000..b015ff344 --- /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 000000000..ca800c0b7 --- /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 000000000..3ce265e27 --- /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 000000000..bdff958d8 --- /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 000000000..7f9faf9ca --- /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 000000000..770179575 --- /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 000000000..089ef92d0 --- /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 000000000..acd032fb0 --- /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 000000000..a6aae5b90 --- /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 000000000..c7649880f --- /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 000000000..ec060aded --- /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 000000000..438e0a64c --- /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 000000000..bb73b0452 --- /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 000000000..a904c54c7 --- /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 000000000..908d46d66 --- /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 000000000..4d557b652 --- /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 000000000..70d904b49 --- /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 000000000..bdfa493bd --- /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 000000000..8ef9fb76a --- /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 000000000..190fc354a --- /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 000000000..d2548ec24 --- /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/stitching/src/precomp.cpp b/modules/cudev/test/test_main.cpp similarity index 95% rename from modules/stitching/src/precomp.cpp rename to modules/cudev/test/test_main.cpp index 390dbfbc6..fc7f8a3b3 100644 --- a/modules/stitching/src/precomp.cpp +++ b/modules/cudev/test/test_main.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,4 +41,6 @@ // //M*/ -#include "precomp.hpp" \ No newline at end of file +#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 000000000..18e7cc1ce --- /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/gpubgsegm/test/test_precomp.cpp b/modules/cudev/test/test_pyramids.cu similarity index 73% rename from modules/gpubgsegm/test/test_precomp.cpp rename to modules/cudev/test/test_pyramids.cu index 0fb652180..c196c923c 100644 --- a/modules/gpubgsegm/test/test_precomp.cpp +++ b/modules/cudev/test/test_pyramids.cu @@ -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, @@ -41,3 +42,40 @@ //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 000000000..22cadbebc --- /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 000000000..3af24f588 --- /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 000000000..8777867bf --- /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 000000000..a1e477c22 --- /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 7d36a58ac..0b080cfb9 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 a1ac7b95e..83688c0a3 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 ------------------- @@ -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. @@ -72,15 +77,18 @@ Creates a descriptor extractor by name. .. ocv:function:: Ptr DescriptorExtractor::create( const String& descriptorExtractorType ) +.. ocv:pyfunction:: cv2.DescriptorExtractor_create(descriptorExtractorType) -> retval + :param descriptorExtractorType: Descriptor extractor type. The current implementation supports the following types of a descriptor extractor: * ``"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 4c49cad61..2c2cf28f8 100644 --- a/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst +++ b/modules/features2d/doc/common_interfaces_of_descriptor_matchers.rst @@ -9,6 +9,11 @@ that are represented as vectors in a multidimensional space. All objects that im descriptor matchers inherit the :ocv:class:`DescriptorMatcher` interface. +.. 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 ----------------- @@ -271,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 3bbaa8aca..434585d1e 100644 --- a/modules/features2d/doc/common_interfaces_of_feature_detectors.rst +++ b/modules/features2d/doc/common_interfaces_of_feature_detectors.rst @@ -8,6 +8,9 @@ between different algorithms solving the same problem. All objects that implemen inherit the :ocv:class:`FeatureDetector` interface. +.. note:: + + * An example explaining keypoint detection can be found at opencv_source_code/samples/cpp/descriptor_extractor_matcher.cpp FeatureDetector --------------- @@ -44,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. @@ -60,6 +65,8 @@ Creates a feature detector by its name. .. ocv:function:: Ptr FeatureDetector::create( const String& detectorType ) +.. ocv:pyfunction:: cv2.FeatureDetector_create(detectorType) -> retval + :param detectorType: Feature detector type. The following detector types are supported: @@ -162,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 { @@ -176,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 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 a306c6606..5a7f952bc 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 2669ab9f2..68c68fc6c 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 f265ab3c4..a6fe7c8fa 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. @@ -50,6 +62,10 @@ 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://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 73089ce7a..644634fd0 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 4b21ddb09..af687e308 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -535,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: @@ -646,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 ); @@ -961,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; @@ -1143,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(); @@ -1404,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 ); diff --git a/modules/features2d/include/opencv2/features2d/features2d.hpp b/modules/features2d/include/opencv2/features2d/features2d.hpp index c825295ec..e81df0ad0 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 fe7396183..25b82bd41 100644 --- a/modules/features2d/perf/perf_fast.cpp +++ b/modules/features2d/perf/perf_fast.cpp @@ -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 8552ac3d4..000000000 --- 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 b27b85123..a257f6cbe 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/brisk.cpp b/modules/features2d/src/brisk.cpp index 5513bad85..76bded666 100644 --- a/modules/features2d/src/brisk.cpp +++ b/modules/features2d/src/brisk.cpp @@ -525,7 +525,11 @@ BRISK::operator()( InputArray _image, InputArray _mask, std::vector& 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); } @@ -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); } diff --git a/modules/features2d/src/descriptors.cpp b/modules/features2d/src/descriptors.cpp index 4f434032e..b79768ae1 100644 --- a/modules/features2d/src/descriptors.cpp +++ b/modules/features2d/src/descriptors.cpp @@ -99,7 +99,7 @@ Ptr DescriptorExtractor::create(const String& descriptorExt { size_t pos = String("Opponent").size(); String type = descriptorExtractorType.substr(pos); - return new OpponentColorDescriptorExtractor(DescriptorExtractor::create(type)); + return makePtr(DescriptorExtractor::create(type)); } return Algorithm::create("Feature2D." + descriptorExtractorType); @@ -119,7 +119,7 @@ CV_WRAP void Feature2D::compute( const Mat& image, CV_OUT CV_IN_OUT std::vector< OpponentColorDescriptorExtractor::OpponentColorDescriptorExtractor( const Ptr& _descriptorExtractor ) : descriptorExtractor(_descriptorExtractor) { - CV_Assert( !descriptorExtractor.empty() ); + CV_Assert( descriptorExtractor ); } static void convertBGRImageToOpponentColorSpace( const Mat& bgrImage, std::vector& opponentChannels ) @@ -249,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 c20d57355..63a882dd3 100644 --- a/modules/features2d/src/detectors.cpp +++ b/modules/features2d/src/detectors.cpp @@ -90,19 +90,19 @@ 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")))); } @@ -190,7 +190,7 @@ GridAdaptedFeatureDetector::GridAdaptedFeatureDetector( const Ptrempty(); + return !detector || detector->empty(); } struct ResponseComparator @@ -295,7 +295,7 @@ PyramidAdaptedFeatureDetector::PyramidAdaptedFeatureDetector( const Ptrempty(); + return !detector || detector->empty(); } void PyramidAdaptedFeatureDetector::detectImpl( const Mat& image, std::vector& keypoints, const Mat& mask ) const diff --git a/modules/features2d/src/dynamic.cpp b/modules/features2d/src/dynamic.cpp index d08434da4..6bd6ab4de 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,7 +195,7 @@ 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; } @@ -205,15 +205,15 @@ Ptr AdjusterAdapter::create( const String& detectorType ) 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 cdc5834d4..5bde951d6 100644 --- a/modules/features2d/src/evaluation.cpp +++ b/modules/features2d/src/evaluation.cpp @@ -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,7 +461,7 @@ 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() ) + if( (keypoints1->empty() || keypoints2->empty()) && !fdetector ) CV_Error( Error::StsBadArg, "fdetector must not be empty when keypoints1 or keypoints2 is empty" ); if( keypoints1->empty() ) @@ -575,7 +575,7 @@ void cv::evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, con if( keypoints1.empty() ) CV_Error( Error::StsBadArg, "keypoints1 must not be empty" ); - if( matches1to2->empty() && dmatcher.empty() ) + if( matches1to2->empty() && !dmatcher ) CV_Error( Error::StsBadArg, "dmatch must not be empty when matches1to2 is empty" ); bool computeKeypoints2ByPrj = keypoints2.empty(); diff --git a/modules/features2d/src/fast_score.cpp b/modules/features2d/src/fast_score.cpp index 423b1f950..de697b7c9 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/matchers.cpp b/modules/features2d/src/matchers.cpp index 54da1833e..087c6a78b 100644 --- a/modules/features2d/src/matchers.cpp +++ b/modules/features2d/src/matchers.cpp @@ -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()); @@ -458,31 +458,31 @@ void BFMatcher::radiusMatchImpl( const Mat& queryDescriptors, std::vector 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( Error::StsBadArg, "Unknown matcher name" ); @@ -497,8 +497,8 @@ Ptr DescriptorMatcher::create( const String& descriptorMatche 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); @@ -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); @@ -725,7 +725,7 @@ 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( Error::StsNotImplemented, "deep clone functionality is not implemented, because " @@ -1066,7 +1066,7 @@ Ptr GenericDescriptorMatcher::create( const String& ge 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/precomp.cpp b/modules/features2d/src/precomp.cpp deleted file mode 100644 index 3e0ec42de..000000000 --- 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/test/test_brisk.cpp b/modules/features2d/test/test_brisk.cpp index adac8e2e7..38e07c3f6 100644 --- a/modules/features2d/test/test_brisk.cpp +++ b/modules/features2d/test/test_brisk.cpp @@ -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 548e81884..08eb59eae 100644 --- a/modules/features2d/test/test_descriptors_regression.cpp +++ b/modules/features2d/test/test_descriptors_regression.cpp @@ -141,7 +141,7 @@ protected: void emptyDataTest() { - assert( !dextractor.empty() ); + assert( dextractor ); // One image. Mat image; @@ -186,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; @@ -267,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 9a88c42f7..8f34913a9 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 76d791864..d500ce549 100644 --- a/modules/features2d/test/test_fast.cpp +++ b/modules/features2d/test/test_fast.cpp @@ -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 7bc5c6e9a..e15d4fa17 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 1627886ba..6b1b4ef63 100644 --- a/modules/features2d/test/test_mser.cpp +++ b/modules/features2d/test/test_mser.cpp @@ -205,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.cpp b/modules/features2d/test/test_precomp.cpp deleted file mode 100644 index 5956e13e3..000000000 --- a/modules/features2d/test/test_precomp.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "test_precomp.hpp" diff --git a/modules/features2d/test/test_rotation_and_scale_invariance.cpp b/modules/features2d/test/test_rotation_and_scale_invariance.cpp index dd0e48e7d..adfe42804 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: @@ -307,8 +307,8 @@ public: normType(_normType), minDescInliersRatio(_minDescInliersRatio) { - CV_Assert(!featureDetector.empty()); - CV_Assert(!descriptorExtractor.empty()); + CV_Assert(featureDetector); + CV_Assert(descriptorExtractor); } protected: @@ -392,7 +392,7 @@ public: minKeyPointMatchesRatio(_minKeyPointMatchesRatio), minScaleInliersRatio(_minScaleInliersRatio) { - CV_Assert(!featureDetector.empty()); + CV_Assert(featureDetector); } protected: @@ -510,8 +510,8 @@ public: normType(_normType), minDescInliersRatio(_minDescInliersRatio) { - CV_Assert(!featureDetector.empty()); - CV_Assert(!descriptorExtractor.empty()); + CV_Assert(featureDetector); + CV_Assert(descriptorExtractor); } protected: diff --git a/modules/flann/CMakeLists.txt b/modules/flann/CMakeLists.txt index 645e8ce85..a6326c40a 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/include/opencv2/flann/any.h b/modules/flann/include/opencv2/flann/any.h index 4042db67c..070d5a421 100644 --- a/modules/flann/include/opencv2/flann/any.h +++ b/modules/flann/include/opencv2/flann/any.h @@ -257,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 e001da7cd..dd4cc421d 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 diff --git a/modules/flann/include/opencv2/flann/flann.hpp b/modules/flann/include/opencv2/flann/flann.hpp index f40aaf79f..227683f97 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/random.h b/modules/flann/include/opencv2/flann/random.h index 2a67352da..a3cf5ec53 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 7bb709b76..3adad4659 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 43d0e1f2a..7ebb7eda7 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/precomp.cpp b/modules/flann/src/precomp.cpp deleted file mode 100644 index c149df18f..000000000 --- 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 b16e4a518..1c4154285 100644 --- a/modules/flann/src/precomp.hpp +++ b/modules/flann/src/precomp.hpp @@ -23,4 +23,3 @@ #include "opencv2/core/private.hpp" #endif - diff --git a/modules/flann/test/test_precomp.cpp b/modules/flann/test/test_precomp.cpp deleted file mode 100644 index 5956e13e3..000000000 --- a/modules/flann/test/test_precomp.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "test_precomp.hpp" diff --git a/modules/gpu/doc/data_structures.rst b/modules/gpu/doc/data_structures.rst index 823d3c309..2a2171035 100644 --- a/modules/gpu/doc/data_structures.rst +++ b/modules/gpu/doc/data_structures.rst @@ -309,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/initalization_and_information.rst b/modules/gpu/doc/initalization_and_information.rst index ad4b29d42..abfc0860c 100644 --- a/modules/gpu/doc/initalization_and_information.rst +++ b/modules/gpu/doc/initalization_and_information.rst @@ -147,10 +147,10 @@ Class providing functionality for querying the specified GPU properties. :: size_t totalConstMem() const; //! major compute capability - int major() const; + int majorVersion() const; //! minor compute capability - int minor() const; + int minorVersion() const; //! alignment requirement for textures size_t textureAlignment() const; @@ -313,19 +313,19 @@ Returns the device name. -gpu::DeviceInfo::major ----------------------- +gpu::DeviceInfo::majorVersion +----------------------------- Returns the major compute capability version. -.. ocv:function:: int gpu::DeviceInfo::major() +.. ocv:function:: int gpu::DeviceInfo::majorVersion() -gpu::DeviceInfo::minor ----------------------- +gpu::DeviceInfo::minorVersion +----------------------------- Returns the minor compute capability version. -.. ocv:function:: int gpu::DeviceInfo::minor() +.. ocv:function:: int gpu::DeviceInfo::minorVersion() diff --git a/modules/gpu/doc/introduction.rst b/modules/gpu/doc/introduction.rst index ef34c369b..a1237629c 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 010124410..52755608b 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 ------------------------------------- @@ -229,7 +234,10 @@ 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 ----------------------------------------------------- diff --git a/modules/gpu/misc/mark_nvidia.py b/modules/gpu/misc/mark_nvidia.py index 08743fb13..80dc7f9ce 100755 --- a/modules/gpu/misc/mark_nvidia.py +++ b/modules/gpu/misc/mark_nvidia.py @@ -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_main.cpp b/modules/gpu/perf/perf_main.cpp index a7ac1ccce..802d559af 100644 --- a/modules/gpu/perf/perf_main.cpp +++ b/modules/gpu/perf/perf_main.cpp @@ -44,4 +44,4 @@ using namespace perf; -CV_PERF_TEST_MAIN(gpu, printCudaInfo()) +CV_PERF_TEST_CUDA_MAIN(gpu) diff --git a/modules/gpu/perf/perf_precomp.cpp b/modules/gpu/perf/perf_precomp.cpp deleted file mode 100644 index 81f16e8f1..000000000 --- a/modules/gpu/perf/perf_precomp.cpp +++ /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 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" diff --git a/modules/gpu/perf4au/main.cpp b/modules/gpu/perf4au/main.cpp index d86f7b8f3..707251c42 100644 --- a/modules/gpu/perf4au/main.cpp +++ b/modules/gpu/perf4au/main.cpp @@ -52,16 +52,12 @@ #include "opencv2/ts.hpp" #include "opencv2/ts/gpu_perf.hpp" -int main(int argc, char* argv[]) -{ - perf::printCudaInfo(); +static const char * impls[] = { + "cuda", + "plain" +}; - perf::Regression::Init("gpu_perf4au"); - perf::TestBase::Init(argc, argv); - testing::InitGoogleTest(&argc, argv); - - return RUN_ALL_TESTS(); -} +CV_PERF_TEST_MAIN_WITH_IMPLS(gpu_perf4au, impls, perf::printCudaInfo()) ////////////////////////////////////////////////////////// // HoughLinesP @@ -86,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 @@ -147,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/calib3d.cpp b/modules/gpu/src/calib3d.cpp index 9e912582a..631174218 100644 --- a/modules/gpu/src/calib3d.cpp +++ b/modules/gpu/src/calib3d.cpp @@ -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 74867b48d..fc5eafbf4 100644 --- a/modules/gpu/src/cascadeclassifier.cpp +++ b/modules/gpu/src/cascadeclassifier.cpp @@ -207,8 +207,8 @@ private: 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); @@ -217,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); @@ -228,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); @@ -279,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); diff --git a/modules/gpu/src/precomp.cpp b/modules/gpu/src/precomp.cpp deleted file mode 100644 index 3c01a2596..000000000 --- a/modules/gpu/src/precomp.cpp +++ /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 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" diff --git a/modules/gpu/test/test_precomp.cpp b/modules/gpu/test/test_precomp.cpp deleted file mode 100644 index 0fb652180..000000000 --- a/modules/gpu/test/test_precomp.cpp +++ /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 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" diff --git a/modules/gpu/test/test_precomp.hpp b/modules/gpu/test/test_precomp.hpp index f2b0bf405..0a9c1df3d 100644 --- a/modules/gpu/test/test_precomp.hpp +++ b/modules/gpu/test/test_precomp.hpp @@ -62,4 +62,6 @@ #include "opencv2/calib3d.hpp" #include "opencv2/objdetect.hpp" +#include "cvconfig.h" + #endif diff --git a/modules/gpu/test/test_stream.cpp b/modules/gpu/test/test_stream.cpp index a34a4e840..4ce29db75 100644 --- a/modules/gpu/test/test_stream.cpp +++ b/modules/gpu/test/test_stream.cpp @@ -44,10 +44,12 @@ #ifdef HAVE_CUDA -using namespace cvtest; +#include #if CUDART_VERSION >= 5000 +using namespace cvtest; + struct Async : testing::TestWithParam { cv::gpu::CudaMem src; @@ -61,20 +63,21 @@ struct Async : testing::TestWithParam cv::gpu::DeviceInfo devInfo = GetParam(); cv::gpu::setDevice(devInfo.deviceID()); + src = cv::gpu::CudaMem(cv::gpu::CudaMem::PAGE_LOCKED); + cv::Mat m = randomMat(cv::Size(128, 128), CV_8UC1); - src.create(m.size(), m.type(), cv::gpu::CudaMem::ALLOC_PAGE_LOCKED); - m.copyTo(src.createMatHeader()); + m.copyTo(src); } }; -void checkMemSet(cv::gpu::Stream&, int status, void* userData) +void checkMemSet(int status, void* userData) { ASSERT_EQ(cudaSuccess, status); Async* test = reinterpret_cast(userData); - cv::Mat src = test->src; - cv::Mat dst = test->dst; + cv::gpu::CudaMem src = test->src; + cv::gpu::CudaMem dst = test->dst; cv::Mat dst_gold = cv::Mat::zeros(src.size(), src.type()); @@ -87,8 +90,8 @@ GPU_TEST_P(Async, MemSet) d_dst.upload(src); - stream.enqueueMemSet(d_dst, cv::Scalar::all(0)); - stream.enqueueDownload(d_dst, dst); + d_dst.setTo(cv::Scalar::all(0), stream); + d_dst.download(dst, stream); Async* test = this; stream.enqueueHostCallback(checkMemSet, test); @@ -96,17 +99,17 @@ GPU_TEST_P(Async, MemSet) stream.waitForCompletion(); } -void checkConvert(cv::gpu::Stream&, int status, void* userData) +void checkConvert(int status, void* userData) { ASSERT_EQ(cudaSuccess, status); Async* test = reinterpret_cast(userData); - cv::Mat src = test->src; - cv::Mat dst = test->dst; + cv::gpu::CudaMem src = test->src; + cv::gpu::CudaMem dst = test->dst; cv::Mat dst_gold; - src.convertTo(dst_gold, CV_32S); + src.createMatHeader().convertTo(dst_gold, CV_32S); ASSERT_MAT_NEAR(dst_gold, dst, 0); } @@ -115,9 +118,9 @@ GPU_TEST_P(Async, Convert) { cv::gpu::Stream stream; - stream.enqueueUpload(src, d_src); - stream.enqueueConvert(d_src, d_dst, CV_32S); - stream.enqueueDownload(d_dst, dst); + d_src.upload(src, stream); + d_src.convertTo(d_dst, CV_32S, stream); + d_dst.download(dst, stream); Async* test = this; stream.enqueueHostCallback(checkConvert, test); @@ -127,6 +130,6 @@ GPU_TEST_P(Async, Convert) INSTANTIATE_TEST_CASE_P(GPU_Stream, Async, ALL_DEVICES); -#endif +#endif // CUDART_VERSION >= 5000 #endif // HAVE_CUDA diff --git a/modules/gpuarithm/include/opencv2/gpuarithm.hpp b/modules/gpuarithm/include/opencv2/gpuarithm.hpp index 8fbe296d8..dabb4e2ab 100644 --- a/modules/gpuarithm/include/opencv2/gpuarithm.hpp +++ b/modules/gpuarithm/include/opencv2/gpuarithm.hpp @@ -49,17 +49,6 @@ #include "opencv2/core/gpu.hpp" -#if defined __GNUC__ - #define __OPENCV_GPUARITHM_DEPR_BEFORE__ - #define __OPENCV_GPUARITHM_DEPR_AFTER__ __attribute__ ((deprecated)) -#elif (defined WIN32 || defined _WIN32) - #define __OPENCV_GPUARITHM_DEPR_BEFORE__ __declspec(deprecated) - #define __OPENCV_GPUARITHM_DEPR_AFTER__ -#else - #define __OPENCV_GPUARITHM_DEPR_BEFORE__ - #define __OPENCV_GPUARITHM_DEPR_AFTER__ -#endif - namespace cv { namespace gpu { //! adds one matrix to another (dst = src1 + src2) @@ -197,13 +186,8 @@ class CV_EXPORTS LookUpTable : public Algorithm public: virtual void transform(InputArray src, OutputArray dst, Stream& stream = Stream::Null()) = 0; }; -CV_EXPORTS Ptr createLookUpTable(InputArray lut); -__OPENCV_GPUARITHM_DEPR_BEFORE__ void LUT(InputArray src, InputArray lut, OutputArray dst, Stream& stream = Stream::Null()) __OPENCV_GPUARITHM_DEPR_AFTER__; -inline void LUT(InputArray src, InputArray lut, OutputArray dst, Stream& stream) -{ - createLookUpTable(lut)->transform(src, dst, stream); -} +CV_EXPORTS Ptr createLookUpTable(InputArray lut); //! copies 2D array to a larger destination array and pads borders with user-specifiable constant CV_EXPORTS void copyMakeBorder(InputArray src, OutputArray dst, int top, int bottom, int left, int right, int borderType, @@ -382,38 +366,9 @@ class CV_EXPORTS Convolution : public Algorithm public: virtual void convolve(InputArray image, InputArray templ, OutputArray result, bool ccorr = false, Stream& stream = Stream::Null()) = 0; }; + CV_EXPORTS Ptr createConvolution(Size user_block_size = Size()); -__OPENCV_GPUARITHM_DEPR_BEFORE__ void convolve(InputArray image, InputArray templ, OutputArray result, bool ccorr = false, Stream& stream = Stream::Null()) __OPENCV_GPUARITHM_DEPR_AFTER__; -inline void convolve(InputArray image, InputArray templ, OutputArray result, bool ccorr , Stream& stream) -{ - createConvolution()->convolve(image, templ, result, ccorr, stream); -} - -struct 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, Size){} - static Size estimateBlockSize(Size, Size){ return Size(); } -}; - -__OPENCV_GPUARITHM_DEPR_BEFORE__ void convolve(InputArray image, InputArray templ, OutputArray result, bool ccorr, ConvolveBuf& buf, Stream& stream = Stream::Null()) __OPENCV_GPUARITHM_DEPR_AFTER__; -inline void convolve(InputArray image, InputArray templ, OutputArray result, bool ccorr, ConvolveBuf& buf, Stream& stream) -{ - createConvolution(buf.user_block_size)->convolve(image, templ, result, ccorr, stream); -} - }} // namespace cv { namespace gpu { -#undef __OPENCV_GPUARITHM_DEPR_BEFORE__ -#undef __OPENCV_GPUARITHM_DEPR_AFTER__ - #endif /* __OPENCV_GPUARITHM_HPP__ */ diff --git a/modules/gpuarithm/perf/perf_arithm.cpp b/modules/gpuarithm/perf/perf_arithm.cpp index dfeafa0fa..b18c8a8c0 100644 --- a/modules/gpuarithm/perf/perf_arithm.cpp +++ b/modules/gpuarithm/perf/perf_arithm.cpp @@ -84,7 +84,7 @@ PERF_TEST_P(Sz_Type_Flags, GEMM, TEST_CYCLE() cv::gpu::gemm(d_src1, d_src2, 1.0, d_src3, 1.0, dst, flags); - GPU_SANITY_CHECK(dst, 1e-6); + GPU_SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); } else { @@ -234,7 +234,7 @@ PERF_TEST_P(Sz_KernelSz_Ccorr, Convolve, TEST_CYCLE() convolution->convolve(d_image, d_templ, dst, ccorr); - GPU_SANITY_CHECK(dst); + GPU_SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); } else { diff --git a/modules/gpuarithm/perf/perf_main.cpp b/modules/gpuarithm/perf/perf_main.cpp index b35791cda..552cf5c16 100644 --- a/modules/gpuarithm/perf/perf_main.cpp +++ b/modules/gpuarithm/perf/perf_main.cpp @@ -44,4 +44,4 @@ using namespace perf; -CV_PERF_TEST_MAIN(gpuarithm, printCudaInfo()) +CV_PERF_TEST_CUDA_MAIN(gpuarithm) diff --git a/modules/gpuarithm/perf/perf_precomp.cpp b/modules/gpuarithm/perf/perf_precomp.cpp deleted file mode 100644 index 81f16e8f1..000000000 --- a/modules/gpuarithm/perf/perf_precomp.cpp +++ /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 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" diff --git a/modules/gpuarithm/src/arithm.cpp b/modules/gpuarithm/src/arithm.cpp index 6045cf5ba..78071ba8a 100644 --- a/modules/gpuarithm/src/arithm.cpp +++ b/modules/gpuarithm/src/arithm.cpp @@ -173,7 +173,7 @@ void cv::gpu::gemm(InputArray _src1, InputArray _src2, double alpha, InputArray (void) _dst; (void) flags; (void) stream; - CV_Error(:Error::StsNotImplemented, "The library was build without CUBLAS"); + CV_Error(Error::StsNotImplemented, "The library was build without CUBLAS"); #else // CUBLAS works with column-major matrices @@ -624,12 +624,12 @@ namespace Ptr cv::gpu::createConvolution(Size user_block_size) { -#ifndef HAVE_CUBLAS +#ifndef HAVE_CUFFT (void) user_block_size; - CV_Error(cv::Error::StsNotImplemented, "The library was build without CUFFT"); - return Ptr(); + CV_Error(Error::StsNotImplemented, "The library was build without CUFFT"); + return Ptr(); #else - return new ConvolutionImpl(user_block_size); + return makePtr(user_block_size); #endif } diff --git a/modules/gpuarithm/src/core.cpp b/modules/gpuarithm/src/core.cpp index 22887796a..05ea5741d 100644 --- a/modules/gpuarithm/src/core.cpp +++ b/modules/gpuarithm/src/core.cpp @@ -497,7 +497,7 @@ namespace Ptr cv::gpu::createLookUpTable(InputArray lut) { - return new LookUpTableImpl(lut); + return makePtr(lut); } //////////////////////////////////////////////////////////////////////// diff --git a/modules/gpuarithm/src/cuda/reduce.cu b/modules/gpuarithm/src/cuda/reduce.cu index 51c354cf9..8588a3b23 100644 --- a/modules/gpuarithm/src/cuda/reduce.cu +++ b/modules/gpuarithm/src/cuda/reduce.cu @@ -72,7 +72,7 @@ namespace reduce } template - __device__ __forceinline__ T result(T r, double) const + __device__ __forceinline__ T result(T r, int) const { return r; } @@ -81,6 +81,15 @@ namespace reduce __host__ __device__ __forceinline__ Sum(const Sum&) {} }; + template struct OutputType + { + typedef float type; + }; + template <> struct OutputType + { + typedef double type; + }; + struct Avg { template @@ -96,7 +105,7 @@ namespace reduce } template - __device__ __forceinline__ typename TypeVec::cn>::vec_type result(T r, double sz) const + __device__ __forceinline__ typename TypeVec::elem_type>::type, VecTraits::cn>::vec_type result(T r, float sz) const { return r / sz; } @@ -121,7 +130,7 @@ namespace reduce } template - __device__ __forceinline__ T result(T r, double) const + __device__ __forceinline__ T result(T r, int) const { return r; } @@ -146,7 +155,7 @@ namespace reduce } template - __device__ __forceinline__ T result(T r, double) const + __device__ __forceinline__ T result(T r, int) const { return r; } diff --git a/modules/gpuarithm/src/element_operations.cpp b/modules/gpuarithm/src/element_operations.cpp index 3ec4f84f6..20473de38 100644 --- a/modules/gpuarithm/src/element_operations.cpp +++ b/modules/gpuarithm/src/element_operations.cpp @@ -1912,7 +1912,7 @@ void cv::gpu::bitwise_not(InputArray _src, OutputArray _dst, InputArray _mask, S } else { - bitMatNot( + bitMatNot( PtrStepSzb(src.rows, bcols, src.data, src.step), PtrStepSzb(src.rows, bcols, dst.data, dst.step), mask, stream); diff --git a/modules/gpuarithm/src/precomp.cpp b/modules/gpuarithm/src/precomp.cpp deleted file mode 100644 index 3c01a2596..000000000 --- a/modules/gpuarithm/src/precomp.cpp +++ /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 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" diff --git a/modules/gpuarithm/test/test_precomp.cpp b/modules/gpuarithm/test/test_precomp.cpp deleted file mode 100644 index 0fb652180..000000000 --- a/modules/gpuarithm/test/test_precomp.cpp +++ /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 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" diff --git a/modules/gpuarithm/test/test_precomp.hpp b/modules/gpuarithm/test/test_precomp.hpp index f9d3ad43c..faa0f5adb 100644 --- a/modules/gpuarithm/test/test_precomp.hpp +++ b/modules/gpuarithm/test/test_precomp.hpp @@ -51,6 +51,8 @@ #ifndef __OPENCV_TEST_PRECOMP_HPP__ #define __OPENCV_TEST_PRECOMP_HPP__ +#include + #include "opencv2/ts.hpp" #include "opencv2/ts/gpu_test.hpp" @@ -58,4 +60,6 @@ #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" +#include "cvconfig.h" + #endif diff --git a/modules/gpubgsegm/CMakeLists.txt b/modules/gpubgsegm/CMakeLists.txt index f37ec595c..f87f3cb88 100644 --- a/modules/gpubgsegm/CMakeLists.txt +++ b/modules/gpubgsegm/CMakeLists.txt @@ -6,4 +6,4 @@ set(the_description "GPU-accelerated Background Segmentation") ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127 /wd4324 /wd4512 -Wundef -Wmissing-declarations) -ocv_define_module(gpubgsegm opencv_video opencv_imgproc opencv_legacy opencv_gpuarithm opencv_gpufilters opencv_gpuimgproc) +ocv_define_module(gpubgsegm opencv_video OPTIONAL opencv_legacy opencv_imgproc opencv_gpuarithm opencv_gpufilters opencv_gpuimgproc) diff --git a/modules/gpubgsegm/doc/background_segmentation.rst b/modules/gpubgsegm/doc/background_segmentation.rst index f892ee666..53e67ead6 100644 --- a/modules/gpubgsegm/doc/background_segmentation.rst +++ b/modules/gpubgsegm/doc/background_segmentation.rst @@ -5,404 +5,123 @@ Background Segmentation -gpu::FGDStatModel ------------------ -.. ocv:class:: gpu::FGDStatModel +gpu::BackgroundSubtractorMOG +---------------------------- +Gaussian Mixture-based Background/Foreground Segmentation Algorithm. -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; - }; +.. ocv:class:: gpu::BackgroundSubtractorMOG : public cv::BackgroundSubtractorMOG 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` +.. note:: + + * An example on gaussian mixture based background/foreground segmantation can be found at opencv_source_code/samples/gpu/bgfg_segm.cpp -gpu::MOG_GPU::MOG_GPU ---------------------- -The constructor. +gpu::createBackgroundSubtractorMOG +---------------------------------- +Creates mixture-of-gaussian background subtractor -.. ocv:function:: gpu::MOG_GPU::MOG_GPU(int nmixtures = -1) +.. ocv:function:: Ptr gpu::createBackgroundSubtractorMOG(int history=200, int nmixtures=5, double backgroundRatio=0.7, double noiseSigma=0) + + :param history: Length of the history. :param nmixtures: Number of Gaussian mixtures. -Default constructor sets all parameters to default values. + :param backgroundRatio: Background ratio. + + :param noiseSigma: Noise strength (standard deviation of the brightness or each color channel). 0 means some automatic value. -gpu::MOG_GPU::operator() ------------------------- -Updates the background model and returns the foreground mask. +gpu::BackgroundSubtractorMOG2 +----------------------------- +Gaussian Mixture-based Background/Foreground Segmentation Algorithm. -.. ocv:function:: void gpu::MOG_GPU::operator()(const GpuMat& frame, GpuMat& fgmask, float learningRate = 0.0f, Stream& stream = Stream::Null()) +.. ocv:class:: gpu::BackgroundSubtractorMOG2 : public cv::BackgroundSubtractorMOG2 - :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. +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]_. .. seealso:: :ocv:class:`BackgroundSubtractorMOG2` -gpu::MOG2_GPU::MOG2_GPU ------------------------ -The constructor. +gpu::createBackgroundSubtractorMOG2 +----------------------------------- +Creates MOG2 Background Subtractor -.. ocv:function:: gpu::MOG2_GPU::MOG2_GPU(int nmixtures = -1) +.. ocv:function:: Ptr gpu::createBackgroundSubtractorMOG2( int history=500, double varThreshold=16, bool detectShadows=true ) - :param nmixtures: Number of Gaussian mixtures. + :param history: Length of the history. -Default constructor sets all parameters to default values. + :param varThreshold: Threshold on the squared Mahalanobis distance between the pixel and the model to decide whether a pixel is well described by the background model. This parameter does not affect the background update. + + :param detectShadows: If true, the algorithm will detect shadows and mark them. It decreases the speed a bit, so if you do not need this feature, set the parameter to false. -gpu::MOG2_GPU::operator() -------------------------- -Updates the background model and returns the foreground mask. +gpu::BackgroundSubtractorGMG +---------------------------- +Background/Foreground Segmentation Algorithm. -.. ocv:function:: void gpu::MOG2_GPU::operator()( const GpuMat& frame, GpuMat& fgmask, float learningRate=-1.0f, Stream& stream=Stream::Null() ) +.. ocv:class:: gpu::BackgroundSubtractorGMG : public cv::BackgroundSubtractorGMG - :param frame: Next video frame. - - :param fgmask: The output foreground mask as an 8-bit binary image. - - :param stream: Stream for the asynchronous version. +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]_. -gpu::MOG2_GPU::getBackgroundImage ---------------------------------- -Computes a background image. +gpu::createBackgroundSubtractorGMG +---------------------------------- +Creates GMG Background Subtractor -.. ocv:function:: void gpu::MOG2_GPU::getBackgroundImage(GpuMat& backgroundImage, Stream& stream = Stream::Null()) const +.. ocv:function:: Ptr gpu::createBackgroundSubtractorGMG(int initializationFrames = 120, double decisionThreshold = 0.8) - :param backgroundImage: The output background image. + :param initializationFrames: Number of frames of video to use to initialize histograms. - :param stream: Stream for the asynchronous version. + :param decisionThreshold: Value above which pixel is determined to be FG. -gpu::MOG2_GPU::release ----------------------- -Releases all inner buffer's memory. +gpu::BackgroundSubtractorFGD +---------------------------- -.. ocv:function:: void gpu::MOG2_GPU::release() +.. ocv:class:: gpu::BackgroundSubtractorFGD : public cv::BackgroundSubtractor +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]_. :: - -gpu::GMG_GPU ------------- -.. ocv:class:: gpu::GMG_GPU - - Class used for background/foreground segmentation. :: - - class GMG_GPU_GPU + class CV_EXPORTS BackgroundSubtractorFGD : public cv::BackgroundSubtractor { 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; - - ... + virtual void getForegroundRegions(OutputArrayOfArrays foreground_regions) = 0; }; - 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. +.. seealso:: :ocv:class:`BackgroundSubtractor` -gpu::GMG_GPU::GMG_GPU ---------------------- -The default constructor. +gpu::BackgroundSubtractorFGD::getForegroundRegions +-------------------------------------------------- +Returns the output foreground regions calculated by :ocv:func:`findContours`. -.. ocv:function:: gpu::GMG_GPU::GMG_GPU() +.. ocv:function:: void gpu::BackgroundSubtractorFGD::getForegroundRegions(OutputArrayOfArrays foreground_regions) -Default constructor sets all parameters to default values. + :params foreground_regions: Output array (CPU memory). -gpu::GMG_GPU::initialize ------------------------- -Initialize background model and allocates all inner buffers. +gpu::createBackgroundSubtractorFGD +---------------------------------- +Creates FGD Background Subtractor -.. ocv:function:: void gpu::GMG_GPU::initialize(Size frameSize, float min = 0.0f, float max = 255.0f) +.. ocv:function:: Ptr gpu::createBackgroundSubtractorFGD(const FGDParams& params = FGDParams()) - :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() + :param params: Algorithm's parameters. See [FGD2003]_ for explanation. .. [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 .. [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/gpubgsegm/include/opencv2/gpubgsegm.hpp b/modules/gpubgsegm/include/opencv2/gpubgsegm.hpp index 3fe62ec94..c6d9223dd 100644 --- a/modules/gpubgsegm/include/opencv2/gpubgsegm.hpp +++ b/modules/gpubgsegm/include/opencv2/gpubgsegm.hpp @@ -47,284 +47,106 @@ # error gpubgsegm.hpp header must be compiled as C++ #endif -#include - #include "opencv2/core/gpu.hpp" -#include "opencv2/gpufilters.hpp" +#include "opencv2/video/background_segm.hpp" namespace cv { namespace gpu { -// 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 +//////////////////////////////////////////////////// +// MOG + +class CV_EXPORTS BackgroundSubtractorMOG : public cv::BackgroundSubtractorMOG { 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. + using cv::BackgroundSubtractorMOG::apply; + using cv::BackgroundSubtractorMOG::getBackgroundImage; - 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. + virtual void apply(InputArray image, OutputArray fgmask, double learningRate, Stream& stream) = 0; - 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_; + virtual void getBackgroundImage(OutputArray backgroundImage, Stream& stream) const = 0; }; -/*! - Gaussian Mixture-based Backbround/Foreground Segmentation Algorithm +CV_EXPORTS Ptr + createBackgroundSubtractorMOG(int history = 200, int nmixtures = 5, + double backgroundRatio = 0.7, double noiseSigma = 0); - 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 +//////////////////////////////////////////////////// +// MOG2 + +class CV_EXPORTS BackgroundSubtractorMOG2 : public cv::BackgroundSubtractorMOG2 { public: - //! the default constructor - MOG_GPU(int nmixtures = -1); + using cv::BackgroundSubtractorMOG2::apply; + using cv::BackgroundSubtractorMOG2::getBackgroundImage; - //! re-initiaization method - void initialize(Size frameSize, int frameType); + virtual void apply(InputArray image, OutputArray fgmask, double learningRate, Stream& stream) = 0; - //! 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_; + virtual void getBackgroundImage(OutputArray backgroundImage, Stream& stream) const = 0; }; -/*! - 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 +CV_EXPORTS Ptr + createBackgroundSubtractorMOG2(int history = 500, double varThreshold = 16, + bool detectShadows = true); + +//////////////////////////////////////////////////// +// GMG + +class CV_EXPORTS BackgroundSubtractorGMG : public cv::BackgroundSubtractorGMG { public: - //! the default constructor - MOG2_GPU(int nmixtures = -1); + using cv::BackgroundSubtractorGMG::apply; - //! 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 + virtual void apply(InputArray image, OutputArray fgmask, double learningRate, Stream& stream) = 0; }; +CV_EXPORTS Ptr + createBackgroundSubtractorGMG(int initializationFrames = 120, double decisionThreshold = 0.8); + +//////////////////////////////////////////////////// +// FGD + /** - * 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. + * 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 GMG_GPU +class CV_EXPORTS BackgroundSubtractorFGD : public cv::BackgroundSubtractor { 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_; + virtual void getForegroundRegions(OutputArrayOfArrays foreground_regions) = 0; }; +struct CV_EXPORTS FGDParams +{ + 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 + FGDParams(); +}; + +CV_EXPORTS Ptr + createBackgroundSubtractorFGD(const FGDParams& params = FGDParams()); + }} // namespace cv { namespace gpu { #endif /* __OPENCV_GPUBGSEGM_HPP__ */ diff --git a/modules/gpubgsegm/perf/perf_bgsegm.cpp b/modules/gpubgsegm/perf/perf_bgsegm.cpp index 15842d59b..34b65f6be 100644 --- a/modules/gpubgsegm/perf/perf_bgsegm.cpp +++ b/modules/gpubgsegm/perf/perf_bgsegm.cpp @@ -41,7 +41,14 @@ //M*/ #include "perf_precomp.hpp" -#include "opencv2/legacy.hpp" + +#ifdef HAVE_OPENCV_LEGACY +# include "opencv2/legacy.hpp" +#endif + +#ifdef HAVE_OPENCV_GPUIMGPROC +# include "opencv2/gpuimgproc.hpp" +#endif using namespace std; using namespace testing; @@ -50,6 +57,7 @@ using namespace perf; #if defined(HAVE_XINE) || \ defined(HAVE_GSTREAMER) || \ defined(HAVE_QUICKTIME) || \ + defined(HAVE_QTKIT) || \ defined(HAVE_AVFOUNDATION) || \ defined(HAVE_FFMPEG) || \ defined(WIN32) /* assume that we have ffmpeg */ @@ -59,18 +67,22 @@ using namespace perf; # define BUILD_WITH_VIDEO_INPUT_SUPPORT 0 #endif +////////////////////////////////////////////////////// +// FGDStatModel + +#if BUILD_WITH_VIDEO_INPUT_SUPPORT + +#ifdef HAVE_OPENCV_LEGACY + namespace cv { - template<> void Ptr::delete_obj() + template<> void DefaultDeleter::operator ()(CvBGStatModel* obj) const { cvReleaseBGStatModel(&obj); } } -////////////////////////////////////////////////////// -// FGDStatModel - -#if BUILD_WITH_VIDEO_INPUT_SUPPORT +#endif DEF_PARAM_TEST_1(Video, string); @@ -90,10 +102,10 @@ PERF_TEST_P(Video, FGDStatModel, if (PERF_RUN_GPU()) { - cv::gpu::GpuMat d_frame(frame); + cv::gpu::GpuMat d_frame(frame), foreground; - cv::gpu::FGDStatModel d_model(4); - d_model.create(d_frame); + cv::Ptr d_fgd = cv::gpu::createBackgroundSubtractorFGD(); + d_fgd->apply(d_frame, foreground); for (int i = 0; i < 10; ++i) { @@ -103,18 +115,22 @@ PERF_TEST_P(Video, FGDStatModel, d_frame.upload(frame); startTimer(); next(); - d_model.update(d_frame); + d_fgd->apply(d_frame, foreground); 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); + +#ifdef HAVE_OPENCV_GPUIMGPROC + cv::gpu::GpuMat background3, background; + d_fgd->getBackgroundImage(background3); + cv::gpu::cvtColor(background3, background, cv::COLOR_BGR2BGRA); + GPU_SANITY_CHECK(background, 1e-2, ERROR_RELATIVE); +#endif } else { +#ifdef HAVE_OPENCV_LEGACY IplImage ipl_frame = frame; cv::Ptr model(cvCreateFGDStatModel(&ipl_frame)); @@ -135,6 +151,9 @@ PERF_TEST_P(Video, FGDStatModel, CPU_SANITY_CHECK(background); CPU_SANITY_CHECK(foreground); +#else + FAIL_NO_CPU(); +#endif } } @@ -176,11 +195,12 @@ PERF_TEST_P(Video_Cn_LearningRate, MOG, if (PERF_RUN_GPU()) { + cv::Ptr d_mog = cv::gpu::createBackgroundSubtractorMOG(); + cv::gpu::GpuMat d_frame(frame); - cv::gpu::MOG_GPU d_mog; cv::gpu::GpuMat foreground; - d_mog(d_frame, foreground, learningRate); + d_mog->apply(d_frame, foreground, learningRate); for (int i = 0; i < 10; ++i) { @@ -200,7 +220,7 @@ PERF_TEST_P(Video_Cn_LearningRate, MOG, d_frame.upload(frame); startTimer(); next(); - d_mog(d_frame, foreground, learningRate); + d_mog->apply(d_frame, foreground, learningRate); stopTimer(); } @@ -273,13 +293,13 @@ PERF_TEST_P(Video_Cn, MOG2, if (PERF_RUN_GPU()) { - cv::gpu::MOG2_GPU d_mog2; - d_mog2.bShadowDetection = false; + cv::Ptr d_mog2 = cv::gpu::createBackgroundSubtractorMOG2(); + d_mog2->setDetectShadows(false); cv::gpu::GpuMat d_frame(frame); cv::gpu::GpuMat foreground; - d_mog2(d_frame, foreground); + d_mog2->apply(d_frame, foreground); for (int i = 0; i < 10; ++i) { @@ -299,7 +319,7 @@ PERF_TEST_P(Video_Cn, MOG2, d_frame.upload(frame); startTimer(); next(); - d_mog2(d_frame, foreground); + d_mog2->apply(d_frame, foreground); stopTimer(); } @@ -307,8 +327,8 @@ PERF_TEST_P(Video_Cn, MOG2, } else { - cv::Ptr mog2 = cv::createBackgroundSubtractorMOG2(); - mog2->set("detectShadows", false); + cv::Ptr mog2 = cv::createBackgroundSubtractorMOG2(); + mog2->setDetectShadows(false); cv::Mat foreground; @@ -359,8 +379,9 @@ PERF_TEST_P(Video_Cn, MOG2GetBackgroundImage, if (PERF_RUN_GPU()) { + cv::Ptr d_mog2 = cv::gpu::createBackgroundSubtractorMOG2(); + cv::gpu::GpuMat d_frame; - cv::gpu::MOG2_GPU d_mog2; cv::gpu::GpuMat d_foreground; for (int i = 0; i < 10; ++i) @@ -380,12 +401,12 @@ PERF_TEST_P(Video_Cn, MOG2GetBackgroundImage, d_frame.upload(frame); - d_mog2(d_frame, d_foreground); + d_mog2->apply(d_frame, d_foreground); } cv::gpu::GpuMat background; - TEST_CYCLE() d_mog2.getBackgroundImage(background); + TEST_CYCLE() d_mog2->getBackgroundImage(background); GPU_SANITY_CHECK(background, 1); } @@ -460,10 +481,10 @@ PERF_TEST_P(Video_Cn_MaxFeatures, GMG, cv::gpu::GpuMat d_frame(frame); cv::gpu::GpuMat foreground; - cv::gpu::GMG_GPU d_gmg; - d_gmg.maxFeatures = maxFeatures; + cv::Ptr d_gmg = cv::gpu::createBackgroundSubtractorGMG(); + d_gmg->setMaxFeatures(maxFeatures); - d_gmg(d_frame, foreground); + d_gmg->apply(d_frame, foreground); for (int i = 0; i < 150; ++i) { @@ -488,7 +509,7 @@ PERF_TEST_P(Video_Cn_MaxFeatures, GMG, d_frame.upload(frame); startTimer(); next(); - d_gmg(d_frame, foreground); + d_gmg->apply(d_frame, foreground); stopTimer(); } @@ -499,9 +520,8 @@ PERF_TEST_P(Video_Cn_MaxFeatures, GMG, cv::Mat foreground; cv::Mat zeros(frame.size(), CV_8UC1, cv::Scalar::all(0)); - cv::Ptr gmg = cv::createBackgroundSubtractorGMG(); - gmg->set("maxFeatures", maxFeatures); - //gmg.initialize(frame.size(), 0.0, 255.0); + cv::Ptr gmg = cv::createBackgroundSubtractorGMG(); + gmg->setMaxFeatures(maxFeatures); gmg->apply(frame, foreground); diff --git a/modules/gpubgsegm/perf/perf_main.cpp b/modules/gpubgsegm/perf/perf_main.cpp index 99066f450..f69d0ea8f 100644 --- a/modules/gpubgsegm/perf/perf_main.cpp +++ b/modules/gpubgsegm/perf/perf_main.cpp @@ -44,4 +44,4 @@ using namespace perf; -CV_PERF_TEST_MAIN(gpubgsegm, printCudaInfo()) +CV_PERF_TEST_CUDA_MAIN(gpubgsegm) diff --git a/modules/gpubgsegm/perf/perf_precomp.cpp b/modules/gpubgsegm/perf/perf_precomp.cpp deleted file mode 100644 index 81f16e8f1..000000000 --- a/modules/gpubgsegm/perf/perf_precomp.cpp +++ /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 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" diff --git a/modules/gpubgsegm/perf/perf_precomp.hpp b/modules/gpubgsegm/perf/perf_precomp.hpp index 3a13b9200..83d0fd4f0 100644 --- a/modules/gpubgsegm/perf/perf_precomp.hpp +++ b/modules/gpubgsegm/perf/perf_precomp.hpp @@ -57,6 +57,8 @@ #include "opencv2/gpubgsegm.hpp" #include "opencv2/video.hpp" +#include "opencv2/opencv_modules.hpp" + #ifdef GTEST_CREATE_SHARED_LIBRARY #error no modules except ts should have GTEST_CREATE_SHARED_LIBRARY defined #endif diff --git a/modules/gpubgsegm/src/cuda/fgd.cu b/modules/gpubgsegm/src/cuda/fgd.cu index 3d5519945..7dd616c71 100644 --- a/modules/gpubgsegm/src/cuda/fgd.cu +++ b/modules/gpubgsegm/src/cuda/fgd.cu @@ -53,7 +53,7 @@ using namespace cv::gpu; using namespace cv::gpu::cudev; -namespace bgfg +namespace fgd { //////////////////////////////////////////////////////////////////////////// // calcDiffHistogram diff --git a/modules/gpubgsegm/src/cuda/fgd.hpp b/modules/gpubgsegm/src/cuda/fgd.hpp index dd7151960..50b9838cd 100644 --- a/modules/gpubgsegm/src/cuda/fgd.hpp +++ b/modules/gpubgsegm/src/cuda/fgd.hpp @@ -45,7 +45,7 @@ #include "opencv2/core/gpu_types.hpp" -namespace bgfg +namespace fgd { struct BGPixelStat { diff --git a/modules/gpubgsegm/src/cuda/gmg.cu b/modules/gpubgsegm/src/cuda/gmg.cu index 8ae9b037b..235c1f0e2 100644 --- a/modules/gpubgsegm/src/cuda/gmg.cu +++ b/modules/gpubgsegm/src/cuda/gmg.cu @@ -47,7 +47,7 @@ #include "opencv2/core/cuda/limits.hpp" namespace cv { namespace gpu { namespace cudev { - namespace bgfg_gmg + namespace gmg { __constant__ int c_width; __constant__ int c_height; diff --git a/modules/gpubgsegm/src/cuda/mog.cu b/modules/gpubgsegm/src/cuda/mog.cu index 6508262d2..ed0720c30 100644 --- a/modules/gpubgsegm/src/cuda/mog.cu +++ b/modules/gpubgsegm/src/cuda/mog.cu @@ -111,14 +111,6 @@ namespace cv { namespace gpu { namespace cudev 0.0f); } - template - __device__ __forceinline__ void swap(Ptr2D& ptr, int x, int y, int k, int rows) - { - typename Ptr2D::elem_type val = ptr(k * rows + y, x); - ptr(k * rows + y, x) = ptr((k + 1) * rows + y, x); - ptr((k + 1) * rows + y, x) = val; - } - /////////////////////////////////////////////////////////////// // MOG without learning @@ -426,337 +418,6 @@ namespace cv { namespace gpu { namespace cudev funcs[cn](weight, mean, dst, nmixtures, backgroundRatio, stream); } - - /////////////////////////////////////////////////////////////// - // MOG2 - - __constant__ int c_nmixtures; - __constant__ float c_Tb; - __constant__ float c_TB; - __constant__ float c_Tg; - __constant__ float c_varInit; - __constant__ float c_varMin; - __constant__ float c_varMax; - __constant__ float c_tau; - __constant__ unsigned char c_shadowVal; - - void loadConstants(int nmixtures, float Tb, float TB, float Tg, float varInit, float varMin, float varMax, float tau, unsigned char shadowVal) - { - varMin = ::fminf(varMin, varMax); - varMax = ::fmaxf(varMin, varMax); - - cudaSafeCall( cudaMemcpyToSymbol(c_nmixtures, &nmixtures, sizeof(int)) ); - cudaSafeCall( cudaMemcpyToSymbol(c_Tb, &Tb, sizeof(float)) ); - cudaSafeCall( cudaMemcpyToSymbol(c_TB, &TB, sizeof(float)) ); - cudaSafeCall( cudaMemcpyToSymbol(c_Tg, &Tg, sizeof(float)) ); - cudaSafeCall( cudaMemcpyToSymbol(c_varInit, &varInit, sizeof(float)) ); - cudaSafeCall( cudaMemcpyToSymbol(c_varMin, &varMin, sizeof(float)) ); - cudaSafeCall( cudaMemcpyToSymbol(c_varMax, &varMax, sizeof(float)) ); - cudaSafeCall( cudaMemcpyToSymbol(c_tau, &tau, sizeof(float)) ); - cudaSafeCall( cudaMemcpyToSymbol(c_shadowVal, &shadowVal, sizeof(unsigned char)) ); - } - - template - __global__ void mog2(const PtrStepSz frame, PtrStepb fgmask, PtrStepb modesUsed, - PtrStepf gmm_weight, PtrStepf gmm_variance, PtrStep gmm_mean, - const float alphaT, const float alpha1, const float prune) - { - 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; - - WorkT pix = cvt(frame(y, x)); - - //calculate distances to the modes (+ sort) - //here we need to go in descending order!!! - - bool background = false; // true - the pixel classified as background - - //internal: - - bool fitsPDF = false; //if it remains zero a new GMM mode will be added - - int nmodes = modesUsed(y, x); - int nNewModes = nmodes; //current number of modes in GMM - - float totalWeight = 0.0f; - - //go through all modes - - for (int mode = 0; mode < nmodes; ++mode) - { - //need only weight if fit is found - float weight = alpha1 * gmm_weight(mode * frame.rows + y, x) + prune; - - //fit not found yet - if (!fitsPDF) - { - //check if it belongs to some of the remaining modes - float var = gmm_variance(mode * frame.rows + y, x); - - WorkT mean = gmm_mean(mode * frame.rows + y, x); - - //calculate difference and distance - WorkT diff = mean - pix; - float dist2 = sqr(diff); - - //background? - Tb - usually larger than Tg - if (totalWeight < c_TB && dist2 < c_Tb * var) - background = true; - - //check fit - if (dist2 < c_Tg * var) - { - //belongs to the mode - fitsPDF = true; - - //update distribution - - //update weight - weight += alphaT; - float k = alphaT / weight; - - //update mean - gmm_mean(mode * frame.rows + y, x) = mean - k * diff; - - //update variance - float varnew = var + k * (dist2 - var); - - //limit the variance - varnew = ::fmaxf(varnew, c_varMin); - varnew = ::fminf(varnew, c_varMax); - - gmm_variance(mode * frame.rows + y, x) = varnew; - - //sort - //all other weights are at the same place and - //only the matched (iModes) is higher -> just find the new place for it - - for (int i = mode; i > 0; --i) - { - //check one up - if (weight < gmm_weight((i - 1) * frame.rows + y, x)) - break; - - //swap one up - swap(gmm_weight, x, y, i - 1, frame.rows); - swap(gmm_variance, x, y, i - 1, frame.rows); - swap(gmm_mean, x, y, i - 1, frame.rows); - } - - //belongs to the mode - bFitsPDF becomes 1 - } - } // !fitsPDF - - //check prune - if (weight < -prune) - { - weight = 0.0; - nmodes--; - } - - gmm_weight(mode * frame.rows + y, x) = weight; //update weight by the calculated value - totalWeight += weight; - } - - //renormalize weights - - totalWeight = 1.f / totalWeight; - for (int mode = 0; mode < nmodes; ++mode) - gmm_weight(mode * frame.rows + y, x) *= totalWeight; - - nmodes = nNewModes; - - //make new mode if needed and exit - - if (!fitsPDF) - { - // replace the weakest or add a new one - int mode = nmodes == c_nmixtures ? c_nmixtures - 1 : nmodes++; - - if (nmodes == 1) - gmm_weight(mode * frame.rows + y, x) = 1.f; - else - { - gmm_weight(mode * frame.rows + y, x) = alphaT; - - // renormalize all other weights - - for (int i = 0; i < nmodes - 1; ++i) - gmm_weight(i * frame.rows + y, x) *= alpha1; - } - - // init - - gmm_mean(mode * frame.rows + y, x) = pix; - gmm_variance(mode * frame.rows + y, x) = c_varInit; - - //sort - //find the new place for it - - for (int i = nmodes - 1; i > 0; --i) - { - // check one up - if (alphaT < gmm_weight((i - 1) * frame.rows + y, x)) - break; - - //swap one up - swap(gmm_weight, x, y, i - 1, frame.rows); - swap(gmm_variance, x, y, i - 1, frame.rows); - swap(gmm_mean, x, y, i - 1, frame.rows); - } - } - - //set the number of modes - modesUsed(y, x) = nmodes; - - bool isShadow = false; - if (detectShadows && !background) - { - float tWeight = 0.0f; - - // check all the components marked as background: - for (int mode = 0; mode < nmodes; ++mode) - { - WorkT mean = gmm_mean(mode * frame.rows + y, x); - - WorkT pix_mean = pix * mean; - - float numerator = sum(pix_mean); - float denominator = sqr(mean); - - // no division by zero allowed - if (denominator == 0) - break; - - // if tau < a < 1 then also check the color distortion - if (numerator <= denominator && numerator >= c_tau * denominator) - { - float a = numerator / denominator; - - WorkT dD = a * mean - pix; - - if (sqr(dD) < c_Tb * gmm_variance(mode * frame.rows + y, x) * a * a) - { - isShadow = true; - break; - } - }; - - tWeight += gmm_weight(mode * frame.rows + y, x); - if (tWeight > c_TB) - break; - } - } - - fgmask(y, x) = background ? 0 : isShadow ? c_shadowVal : 255; - } - - template - void mog2_caller(PtrStepSzb frame, PtrStepSzb fgmask, PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzf variance, PtrStepSzb mean, - float alphaT, float prune, bool detectShadows, cudaStream_t stream) - { - dim3 block(32, 8); - dim3 grid(divUp(frame.cols, block.x), divUp(frame.rows, block.y)); - - const float alpha1 = 1.0f - alphaT; - - if (detectShadows) - { - cudaSafeCall( cudaFuncSetCacheConfig(mog2, cudaFuncCachePreferL1) ); - - mog2<<>>((PtrStepSz) frame, fgmask, modesUsed, - weight, variance, (PtrStepSz) mean, - alphaT, alpha1, prune); - } - else - { - cudaSafeCall( cudaFuncSetCacheConfig(mog2, cudaFuncCachePreferL1) ); - - mog2<<>>((PtrStepSz) frame, fgmask, modesUsed, - weight, variance, (PtrStepSz) mean, - alphaT, alpha1, prune); - } - - cudaSafeCall( cudaGetLastError() ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - - 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) - { - typedef void (*func_t)(PtrStepSzb frame, PtrStepSzb fgmask, PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzf variance, PtrStepSzb mean, float alphaT, float prune, bool detectShadows, cudaStream_t stream); - - static const func_t funcs[] = - { - 0, mog2_caller, 0, mog2_caller, mog2_caller - }; - - funcs[cn](frame, fgmask, modesUsed, weight, variance, mean, alphaT, prune, detectShadows, stream); - } - - template - __global__ void getBackgroundImage2(const PtrStepSzb modesUsed, const PtrStepf gmm_weight, const PtrStep gmm_mean, PtrStep dst) - { - const int x = blockIdx.x * blockDim.x + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (x >= modesUsed.cols || y >= modesUsed.rows) - return; - - int nmodes = modesUsed(y, x); - - WorkT meanVal = VecTraits::all(0.0f); - float totalWeight = 0.0f; - - for (int mode = 0; mode < nmodes; ++mode) - { - float weight = gmm_weight(mode * modesUsed.rows + y, x); - - WorkT mean = gmm_mean(mode * modesUsed.rows + y, x); - meanVal = meanVal + weight * mean; - - totalWeight += weight; - - if(totalWeight > c_TB) - break; - } - - meanVal = meanVal * (1.f / totalWeight); - - dst(y, x) = saturate_cast(meanVal); - } - - template - void getBackgroundImage2_caller(PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzb mean, PtrStepSzb dst, cudaStream_t stream) - { - dim3 block(32, 8); - dim3 grid(divUp(modesUsed.cols, block.x), divUp(modesUsed.rows, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(getBackgroundImage2, cudaFuncCachePreferL1) ); - - getBackgroundImage2<<>>(modesUsed, weight, (PtrStepSz) mean, (PtrStepSz) dst); - cudaSafeCall( cudaGetLastError() ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - - void getBackgroundImage2_gpu(int cn, PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzb mean, PtrStepSzb dst, cudaStream_t stream) - { - typedef void (*func_t)(PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzb mean, PtrStepSzb dst, cudaStream_t stream); - - static const func_t funcs[] = - { - 0, getBackgroundImage2_caller, 0, getBackgroundImage2_caller, getBackgroundImage2_caller - }; - - funcs[cn](modesUsed, weight, mean, dst, stream); - } } }}} diff --git a/modules/gpubgsegm/src/cuda/mog2.cu b/modules/gpubgsegm/src/cuda/mog2.cu new file mode 100644 index 000000000..50cb9fa56 --- /dev/null +++ b/modules/gpubgsegm/src/cuda/mog2.cu @@ -0,0 +1,438 @@ +/*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/core/cuda/common.hpp" +#include "opencv2/core/cuda/vec_traits.hpp" +#include "opencv2/core/cuda/vec_math.hpp" +#include "opencv2/core/cuda/limits.hpp" + +namespace cv { namespace gpu { namespace cudev +{ + namespace mog2 + { + /////////////////////////////////////////////////////////////// + // Utility + + __device__ __forceinline__ float cvt(uchar val) + { + return val; + } + __device__ __forceinline__ float3 cvt(const uchar3& val) + { + return make_float3(val.x, val.y, val.z); + } + __device__ __forceinline__ float4 cvt(const uchar4& val) + { + return make_float4(val.x, val.y, val.z, val.w); + } + + __device__ __forceinline__ float sqr(float val) + { + return val * val; + } + __device__ __forceinline__ float sqr(const float3& val) + { + return val.x * val.x + val.y * val.y + val.z * val.z; + } + __device__ __forceinline__ float sqr(const float4& val) + { + return val.x * val.x + val.y * val.y + val.z * val.z; + } + + __device__ __forceinline__ float sum(float val) + { + return val; + } + __device__ __forceinline__ float sum(const float3& val) + { + return val.x + val.y + val.z; + } + __device__ __forceinline__ float sum(const float4& val) + { + return val.x + val.y + val.z; + } + + template + __device__ __forceinline__ void swap(Ptr2D& ptr, int x, int y, int k, int rows) + { + typename Ptr2D::elem_type val = ptr(k * rows + y, x); + ptr(k * rows + y, x) = ptr((k + 1) * rows + y, x); + ptr((k + 1) * rows + y, x) = val; + } + + /////////////////////////////////////////////////////////////// + // MOG2 + + __constant__ int c_nmixtures; + __constant__ float c_Tb; + __constant__ float c_TB; + __constant__ float c_Tg; + __constant__ float c_varInit; + __constant__ float c_varMin; + __constant__ float c_varMax; + __constant__ float c_tau; + __constant__ unsigned char c_shadowVal; + + void loadConstants(int nmixtures, float Tb, float TB, float Tg, float varInit, float varMin, float varMax, float tau, unsigned char shadowVal) + { + varMin = ::fminf(varMin, varMax); + varMax = ::fmaxf(varMin, varMax); + + cudaSafeCall( cudaMemcpyToSymbol(c_nmixtures, &nmixtures, sizeof(int)) ); + cudaSafeCall( cudaMemcpyToSymbol(c_Tb, &Tb, sizeof(float)) ); + cudaSafeCall( cudaMemcpyToSymbol(c_TB, &TB, sizeof(float)) ); + cudaSafeCall( cudaMemcpyToSymbol(c_Tg, &Tg, sizeof(float)) ); + cudaSafeCall( cudaMemcpyToSymbol(c_varInit, &varInit, sizeof(float)) ); + cudaSafeCall( cudaMemcpyToSymbol(c_varMin, &varMin, sizeof(float)) ); + cudaSafeCall( cudaMemcpyToSymbol(c_varMax, &varMax, sizeof(float)) ); + cudaSafeCall( cudaMemcpyToSymbol(c_tau, &tau, sizeof(float)) ); + cudaSafeCall( cudaMemcpyToSymbol(c_shadowVal, &shadowVal, sizeof(unsigned char)) ); + } + + template + __global__ void mog2(const PtrStepSz frame, PtrStepb fgmask, PtrStepb modesUsed, + PtrStepf gmm_weight, PtrStepf gmm_variance, PtrStep gmm_mean, + const float alphaT, const float alpha1, const float prune) + { + 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; + + WorkT pix = cvt(frame(y, x)); + + //calculate distances to the modes (+ sort) + //here we need to go in descending order!!! + + bool background = false; // true - the pixel classified as background + + //internal: + + bool fitsPDF = false; //if it remains zero a new GMM mode will be added + + int nmodes = modesUsed(y, x); + int nNewModes = nmodes; //current number of modes in GMM + + float totalWeight = 0.0f; + + //go through all modes + + for (int mode = 0; mode < nmodes; ++mode) + { + //need only weight if fit is found + float weight = alpha1 * gmm_weight(mode * frame.rows + y, x) + prune; + + //fit not found yet + if (!fitsPDF) + { + //check if it belongs to some of the remaining modes + float var = gmm_variance(mode * frame.rows + y, x); + + WorkT mean = gmm_mean(mode * frame.rows + y, x); + + //calculate difference and distance + WorkT diff = mean - pix; + float dist2 = sqr(diff); + + //background? - Tb - usually larger than Tg + if (totalWeight < c_TB && dist2 < c_Tb * var) + background = true; + + //check fit + if (dist2 < c_Tg * var) + { + //belongs to the mode + fitsPDF = true; + + //update distribution + + //update weight + weight += alphaT; + float k = alphaT / weight; + + //update mean + gmm_mean(mode * frame.rows + y, x) = mean - k * diff; + + //update variance + float varnew = var + k * (dist2 - var); + + //limit the variance + varnew = ::fmaxf(varnew, c_varMin); + varnew = ::fminf(varnew, c_varMax); + + gmm_variance(mode * frame.rows + y, x) = varnew; + + //sort + //all other weights are at the same place and + //only the matched (iModes) is higher -> just find the new place for it + + for (int i = mode; i > 0; --i) + { + //check one up + if (weight < gmm_weight((i - 1) * frame.rows + y, x)) + break; + + //swap one up + swap(gmm_weight, x, y, i - 1, frame.rows); + swap(gmm_variance, x, y, i - 1, frame.rows); + swap(gmm_mean, x, y, i - 1, frame.rows); + } + + //belongs to the mode - bFitsPDF becomes 1 + } + } // !fitsPDF + + //check prune + if (weight < -prune) + { + weight = 0.0f; + nmodes--; + } + + gmm_weight(mode * frame.rows + y, x) = weight; //update weight by the calculated value + totalWeight += weight; + } + + //renormalize weights + + totalWeight = 1.f / totalWeight; + for (int mode = 0; mode < nmodes; ++mode) + gmm_weight(mode * frame.rows + y, x) *= totalWeight; + + nmodes = nNewModes; + + //make new mode if needed and exit + + if (!fitsPDF) + { + // replace the weakest or add a new one + int mode = nmodes == c_nmixtures ? c_nmixtures - 1 : nmodes++; + + if (nmodes == 1) + gmm_weight(mode * frame.rows + y, x) = 1.f; + else + { + gmm_weight(mode * frame.rows + y, x) = alphaT; + + // renormalize all other weights + + for (int i = 0; i < nmodes - 1; ++i) + gmm_weight(i * frame.rows + y, x) *= alpha1; + } + + // init + + gmm_mean(mode * frame.rows + y, x) = pix; + gmm_variance(mode * frame.rows + y, x) = c_varInit; + + //sort + //find the new place for it + + for (int i = nmodes - 1; i > 0; --i) + { + // check one up + if (alphaT < gmm_weight((i - 1) * frame.rows + y, x)) + break; + + //swap one up + swap(gmm_weight, x, y, i - 1, frame.rows); + swap(gmm_variance, x, y, i - 1, frame.rows); + swap(gmm_mean, x, y, i - 1, frame.rows); + } + } + + //set the number of modes + modesUsed(y, x) = nmodes; + + bool isShadow = false; + if (detectShadows && !background) + { + float tWeight = 0.0f; + + // check all the components marked as background: + for (int mode = 0; mode < nmodes; ++mode) + { + WorkT mean = gmm_mean(mode * frame.rows + y, x); + + WorkT pix_mean = pix * mean; + + float numerator = sum(pix_mean); + float denominator = sqr(mean); + + // no division by zero allowed + if (denominator == 0) + break; + + // if tau < a < 1 then also check the color distortion + if (numerator <= denominator && numerator >= c_tau * denominator) + { + float a = numerator / denominator; + + WorkT dD = a * mean - pix; + + if (sqr(dD) < c_Tb * gmm_variance(mode * frame.rows + y, x) * a * a) + { + isShadow = true; + break; + } + }; + + tWeight += gmm_weight(mode * frame.rows + y, x); + if (tWeight > c_TB) + break; + } + } + + fgmask(y, x) = background ? 0 : isShadow ? c_shadowVal : 255; + } + + template + void mog2_caller(PtrStepSzb frame, PtrStepSzb fgmask, PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzf variance, PtrStepSzb mean, + float alphaT, float prune, bool detectShadows, cudaStream_t stream) + { + dim3 block(32, 8); + dim3 grid(divUp(frame.cols, block.x), divUp(frame.rows, block.y)); + + const float alpha1 = 1.0f - alphaT; + + if (detectShadows) + { + cudaSafeCall( cudaFuncSetCacheConfig(mog2, cudaFuncCachePreferL1) ); + + mog2<<>>((PtrStepSz) frame, fgmask, modesUsed, + weight, variance, (PtrStepSz) mean, + alphaT, alpha1, prune); + } + else + { + cudaSafeCall( cudaFuncSetCacheConfig(mog2, cudaFuncCachePreferL1) ); + + mog2<<>>((PtrStepSz) frame, fgmask, modesUsed, + weight, variance, (PtrStepSz) mean, + alphaT, alpha1, prune); + } + + cudaSafeCall( cudaGetLastError() ); + + if (stream == 0) + cudaSafeCall( cudaDeviceSynchronize() ); + } + + 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) + { + typedef void (*func_t)(PtrStepSzb frame, PtrStepSzb fgmask, PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzf variance, PtrStepSzb mean, float alphaT, float prune, bool detectShadows, cudaStream_t stream); + + static const func_t funcs[] = + { + 0, mog2_caller, 0, mog2_caller, mog2_caller + }; + + funcs[cn](frame, fgmask, modesUsed, weight, variance, mean, alphaT, prune, detectShadows, stream); + } + + template + __global__ void getBackgroundImage2(const PtrStepSzb modesUsed, const PtrStepf gmm_weight, const PtrStep gmm_mean, PtrStep dst) + { + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= modesUsed.cols || y >= modesUsed.rows) + return; + + int nmodes = modesUsed(y, x); + + WorkT meanVal = VecTraits::all(0.0f); + float totalWeight = 0.0f; + + for (int mode = 0; mode < nmodes; ++mode) + { + float weight = gmm_weight(mode * modesUsed.rows + y, x); + + WorkT mean = gmm_mean(mode * modesUsed.rows + y, x); + meanVal = meanVal + weight * mean; + + totalWeight += weight; + + if(totalWeight > c_TB) + break; + } + + meanVal = meanVal * (1.f / totalWeight); + + dst(y, x) = saturate_cast(meanVal); + } + + template + void getBackgroundImage2_caller(PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzb mean, PtrStepSzb dst, cudaStream_t stream) + { + dim3 block(32, 8); + dim3 grid(divUp(modesUsed.cols, block.x), divUp(modesUsed.rows, block.y)); + + cudaSafeCall( cudaFuncSetCacheConfig(getBackgroundImage2, cudaFuncCachePreferL1) ); + + getBackgroundImage2<<>>(modesUsed, weight, (PtrStepSz) mean, (PtrStepSz) dst); + cudaSafeCall( cudaGetLastError() ); + + if (stream == 0) + cudaSafeCall( cudaDeviceSynchronize() ); + } + + void getBackgroundImage2_gpu(int cn, PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzb mean, PtrStepSzb dst, cudaStream_t stream) + { + typedef void (*func_t)(PtrStepSzb modesUsed, PtrStepSzf weight, PtrStepSzb mean, PtrStepSzb dst, cudaStream_t stream); + + static const func_t funcs[] = + { + 0, getBackgroundImage2_caller, 0, getBackgroundImage2_caller, getBackgroundImage2_caller + }; + + funcs[cn](modesUsed, weight, mean, dst, stream); + } + } +}}} + + +#endif /* CUDA_DISABLER */ diff --git a/modules/gpubgsegm/src/fgd.cpp b/modules/gpubgsegm/src/fgd.cpp index fb14ff172..31cf370c1 100644 --- a/modules/gpubgsegm/src/fgd.cpp +++ b/modules/gpubgsegm/src/fgd.cpp @@ -42,329 +42,150 @@ #include "precomp.hpp" -#if !defined HAVE_CUDA || defined(CUDA_DISABLER) +using namespace cv; +using namespace cv::gpu; -class cv::gpu::FGDStatModel::Impl -{ -}; +#if !defined(HAVE_CUDA) || defined(CUDA_DISABLER) || !defined(HAVE_OPENCV_IMGPROC) || !defined(HAVE_OPENCV_GPUARITHM) || !defined(HAVE_OPENCV_GPUIMGPROC) -cv::gpu::FGDStatModel::Params::Params() { throw_no_cuda(); } +cv::gpu::FGDParams::FGDParams() { throw_no_cuda(); } -cv::gpu::FGDStatModel::FGDStatModel(int) { throw_no_cuda(); } -cv::gpu::FGDStatModel::FGDStatModel(const cv::gpu::GpuMat&, const Params&, int) { throw_no_cuda(); } -cv::gpu::FGDStatModel::~FGDStatModel() {} -void cv::gpu::FGDStatModel::create(const cv::gpu::GpuMat&, const Params&) { throw_no_cuda(); } -void cv::gpu::FGDStatModel::release() {} -int cv::gpu::FGDStatModel::update(const cv::gpu::GpuMat&) { throw_no_cuda(); return 0; } +Ptr cv::gpu::createBackgroundSubtractorFGD(const FGDParams&) { throw_no_cuda(); return Ptr(); } #else #include "cuda/fgd.hpp" #include "opencv2/imgproc/imgproc_c.h" -namespace -{ - class BGPixelStat - { - public: - void create(cv::Size size, const cv::gpu::FGDStatModel::Params& params, int out_cn); - void release(); - - void setTrained(); - - operator bgfg::BGPixelStat(); - - private: - cv::gpu::GpuMat Pbc_; - cv::gpu::GpuMat Pbcc_; - cv::gpu::GpuMat is_trained_st_model_; - cv::gpu::GpuMat is_trained_dyn_model_; - - cv::gpu::GpuMat ctable_Pv_; - cv::gpu::GpuMat ctable_Pvb_; - cv::gpu::GpuMat ctable_v_; - - cv::gpu::GpuMat cctable_Pv_; - cv::gpu::GpuMat cctable_Pvb_; - cv::gpu::GpuMat cctable_v1_; - cv::gpu::GpuMat cctable_v2_; - }; - - void BGPixelStat::create(cv::Size size, const cv::gpu::FGDStatModel::Params& params, int out_cn) - { - cv::gpu::ensureSizeIsEnough(size, CV_32FC1, Pbc_); - Pbc_.setTo(cv::Scalar::all(0)); - - cv::gpu::ensureSizeIsEnough(size, CV_32FC1, Pbcc_); - Pbcc_.setTo(cv::Scalar::all(0)); - - cv::gpu::ensureSizeIsEnough(size, CV_8UC1, is_trained_st_model_); - is_trained_st_model_.setTo(cv::Scalar::all(0)); - - cv::gpu::ensureSizeIsEnough(size, CV_8UC1, is_trained_dyn_model_); - is_trained_dyn_model_.setTo(cv::Scalar::all(0)); - - cv::gpu::ensureSizeIsEnough(params.N2c * size.height, size.width, CV_32FC1, ctable_Pv_); - ctable_Pv_.setTo(cv::Scalar::all(0)); - - cv::gpu::ensureSizeIsEnough(params.N2c * size.height, size.width, CV_32FC1, ctable_Pvb_); - ctable_Pvb_.setTo(cv::Scalar::all(0)); - - cv::gpu::ensureSizeIsEnough(params.N2c * size.height, size.width, CV_8UC(out_cn), ctable_v_); - ctable_v_.setTo(cv::Scalar::all(0)); - - cv::gpu::ensureSizeIsEnough(params.N2cc * size.height, size.width, CV_32FC1, cctable_Pv_); - cctable_Pv_.setTo(cv::Scalar::all(0)); - - cv::gpu::ensureSizeIsEnough(params.N2cc * size.height, size.width, CV_32FC1, cctable_Pvb_); - cctable_Pvb_.setTo(cv::Scalar::all(0)); - - cv::gpu::ensureSizeIsEnough(params.N2cc * size.height, size.width, CV_8UC(out_cn), cctable_v1_); - cctable_v1_.setTo(cv::Scalar::all(0)); - - cv::gpu::ensureSizeIsEnough(params.N2cc * size.height, size.width, CV_8UC(out_cn), cctable_v2_); - cctable_v2_.setTo(cv::Scalar::all(0)); - } - - void BGPixelStat::release() - { - Pbc_.release(); - Pbcc_.release(); - is_trained_st_model_.release(); - is_trained_dyn_model_.release(); - - ctable_Pv_.release(); - ctable_Pvb_.release(); - ctable_v_.release(); - - cctable_Pv_.release(); - cctable_Pvb_.release(); - cctable_v1_.release(); - cctable_v2_.release(); - } - - void BGPixelStat::setTrained() - { - is_trained_st_model_.setTo(cv::Scalar::all(1)); - is_trained_dyn_model_.setTo(cv::Scalar::all(1)); - } - - BGPixelStat::operator bgfg::BGPixelStat() - { - bgfg::BGPixelStat stat; - - stat.rows_ = Pbc_.rows; - - stat.Pbc_data_ = Pbc_.data; - stat.Pbc_step_ = Pbc_.step; - - stat.Pbcc_data_ = Pbcc_.data; - stat.Pbcc_step_ = Pbcc_.step; - - stat.is_trained_st_model_data_ = is_trained_st_model_.data; - stat.is_trained_st_model_step_ = is_trained_st_model_.step; - - stat.is_trained_dyn_model_data_ = is_trained_dyn_model_.data; - stat.is_trained_dyn_model_step_ = is_trained_dyn_model_.step; - - stat.ctable_Pv_data_ = ctable_Pv_.data; - stat.ctable_Pv_step_ = ctable_Pv_.step; - - stat.ctable_Pvb_data_ = ctable_Pvb_.data; - stat.ctable_Pvb_step_ = ctable_Pvb_.step; - - stat.ctable_v_data_ = ctable_v_.data; - stat.ctable_v_step_ = ctable_v_.step; - - stat.cctable_Pv_data_ = cctable_Pv_.data; - stat.cctable_Pv_step_ = cctable_Pv_.step; - - stat.cctable_Pvb_data_ = cctable_Pvb_.data; - stat.cctable_Pvb_step_ = cctable_Pvb_.step; - - stat.cctable_v1_data_ = cctable_v1_.data; - stat.cctable_v1_step_ = cctable_v1_.step; - - stat.cctable_v2_data_ = cctable_v2_.data; - stat.cctable_v2_step_ = cctable_v2_.step; - - return stat; - } -} - -class cv::gpu::FGDStatModel::Impl -{ -public: - Impl(cv::gpu::GpuMat& background, cv::gpu::GpuMat& foreground, std::vector< std::vector >& foreground_regions, int out_cn); - ~Impl(); - - void create(const cv::gpu::GpuMat& firstFrame, const cv::gpu::FGDStatModel::Params& params); - void release(); - - int update(const cv::gpu::GpuMat& curFrame); - -private: - Impl(const Impl&); - Impl& operator=(const Impl&); - - int out_cn_; - - cv::gpu::FGDStatModel::Params params_; - - cv::gpu::GpuMat& background_; - cv::gpu::GpuMat& foreground_; - std::vector< std::vector >& foreground_regions_; - - cv::Mat h_foreground_; - - cv::gpu::GpuMat prevFrame_; - cv::gpu::GpuMat Ftd_; - cv::gpu::GpuMat Fbd_; - BGPixelStat stat_; - - cv::gpu::GpuMat hist_; - cv::gpu::GpuMat histBuf_; - - cv::gpu::GpuMat countBuf_; - - cv::gpu::GpuMat buf_; - cv::gpu::GpuMat filterBrd_; - - cv::Ptr dilateFilter_; - cv::Ptr erodeFilter_; - - CvMemStorage* storage_; -}; - -cv::gpu::FGDStatModel::Impl::Impl(cv::gpu::GpuMat& background, cv::gpu::GpuMat& foreground, std::vector< std::vector >& foreground_regions, int out_cn) : - out_cn_(out_cn), background_(background), foreground_(foreground), foreground_regions_(foreground_regions) -{ - CV_Assert( out_cn_ == 3 || out_cn_ == 4 ); - - storage_ = cvCreateMemStorage(); - CV_Assert( storage_ != 0 ); -} - -cv::gpu::FGDStatModel::Impl::~Impl() -{ - cvReleaseMemStorage(&storage_); -} +///////////////////////////////////////////////////////////////////////// +// FGDParams namespace { - void copyChannels(const cv::gpu::GpuMat& src, cv::gpu::GpuMat& dst, int dst_cn = -1) + // Default parameters of foreground detection algorithm: + const int BGFG_FGD_LC = 128; + const int BGFG_FGD_N1C = 15; + const int BGFG_FGD_N2C = 25; + + const int BGFG_FGD_LCC = 64; + const int BGFG_FGD_N1CC = 25; + const int BGFG_FGD_N2CC = 40; + + // Background reference image update parameter: + const float BGFG_FGD_ALPHA_1 = 0.1f; + + // stat model update parameter + // 0.002f ~ 1K frame(~45sec), 0.005 ~ 18sec (if 25fps and absolutely static BG) + const float BGFG_FGD_ALPHA_2 = 0.005f; + + // start value for alpha parameter (to fast initiate statistic model) + const float BGFG_FGD_ALPHA_3 = 0.1f; + + const float BGFG_FGD_DELTA = 2.0f; + + const float BGFG_FGD_T = 0.9f; + + const float BGFG_FGD_MINAREA= 15.0f; +} + +cv::gpu::FGDParams::FGDParams() +{ + Lc = BGFG_FGD_LC; + N1c = BGFG_FGD_N1C; + N2c = BGFG_FGD_N2C; + + Lcc = BGFG_FGD_LCC; + N1cc = BGFG_FGD_N1CC; + N2cc = BGFG_FGD_N2CC; + + delta = BGFG_FGD_DELTA; + + alpha1 = BGFG_FGD_ALPHA_1; + alpha2 = BGFG_FGD_ALPHA_2; + alpha3 = BGFG_FGD_ALPHA_3; + + T = BGFG_FGD_T; + minArea = BGFG_FGD_MINAREA; + + is_obj_without_holes = true; + perform_morphing = 1; +} + +///////////////////////////////////////////////////////////////////////// +// copyChannels + +namespace +{ + void copyChannels(const GpuMat& src, GpuMat& dst, int dst_cn = -1) { const int src_cn = src.channels(); if (dst_cn < 0) dst_cn = src_cn; - cv::gpu::ensureSizeIsEnough(src.size(), CV_MAKE_TYPE(src.depth(), dst_cn), dst); + gpu::ensureSizeIsEnough(src.size(), CV_MAKE_TYPE(src.depth(), dst_cn), dst); if (src_cn == dst_cn) + { src.copyTo(dst); + } else { static const int cvt_codes[4][4] = { - {-1, -1, cv::COLOR_GRAY2BGR, cv::COLOR_GRAY2BGRA}, + {-1, -1, COLOR_GRAY2BGR, COLOR_GRAY2BGRA}, {-1, -1, -1, -1}, - {cv::COLOR_BGR2GRAY, -1, -1, cv::COLOR_BGR2BGRA}, - {cv::COLOR_BGRA2GRAY, -1, cv::COLOR_BGRA2BGR, -1} + {COLOR_BGR2GRAY, -1, -1, COLOR_BGR2BGRA}, + {COLOR_BGRA2GRAY, -1, COLOR_BGRA2BGR, -1} }; const int cvt_code = cvt_codes[src_cn - 1][dst_cn - 1]; CV_DbgAssert( cvt_code >= 0 ); - cv::gpu::cvtColor(src, dst, cvt_code, dst_cn); + gpu::cvtColor(src, dst, cvt_code, dst_cn); } } } -void cv::gpu::FGDStatModel::Impl::create(const cv::gpu::GpuMat& firstFrame, const cv::gpu::FGDStatModel::Params& params) -{ - CV_Assert(firstFrame.type() == CV_8UC3 || firstFrame.type() == CV_8UC4); - - params_ = params; - - cv::gpu::ensureSizeIsEnough(firstFrame.size(), CV_8UC1, foreground_); - - copyChannels(firstFrame, background_, out_cn_); - - copyChannels(firstFrame, prevFrame_); - - cv::gpu::ensureSizeIsEnough(firstFrame.size(), CV_8UC1, Ftd_); - cv::gpu::ensureSizeIsEnough(firstFrame.size(), CV_8UC1, Fbd_); - - stat_.create(firstFrame.size(), params_, out_cn_); - bgfg::setBGPixelStat(stat_); - - if (params_.perform_morphing > 0) - { - cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(1 + params_.perform_morphing * 2, 1 + params_.perform_morphing * 2)); - cv::Point anchor(params_.perform_morphing, params_.perform_morphing); - - dilateFilter_ = cv::gpu::createMorphologyFilter(cv::MORPH_DILATE, CV_8UC1, kernel, anchor); - erodeFilter_ = cv::gpu::createMorphologyFilter(cv::MORPH_ERODE, CV_8UC1, kernel, anchor); - } -} - -void cv::gpu::FGDStatModel::Impl::release() -{ - background_.release(); - foreground_.release(); - - prevFrame_.release(); - Ftd_.release(); - Fbd_.release(); - stat_.release(); - - hist_.release(); - histBuf_.release(); - - countBuf_.release(); - - buf_.release(); - filterBrd_.release(); -} - ///////////////////////////////////////////////////////////////////////// // changeDetection namespace { - void calcDiffHistogram(const cv::gpu::GpuMat& prevFrame, const cv::gpu::GpuMat& curFrame, cv::gpu::GpuMat& hist, cv::gpu::GpuMat& histBuf) + void calcDiffHistogram(const GpuMat& prevFrame, const GpuMat& curFrame, GpuMat& hist, GpuMat& histBuf) { - typedef void (*func_t)(cv::gpu::PtrStepSzb prevFrame, cv::gpu::PtrStepSzb curFrame, unsigned int* hist0, unsigned int* hist1, unsigned int* hist2, unsigned int* partialBuf0, unsigned int* partialBuf1, unsigned int* partialBuf2, bool cc20, cudaStream_t stream); + typedef void (*func_t)(PtrStepSzb prevFrame, PtrStepSzb curFrame, + unsigned int* hist0, unsigned int* hist1, unsigned int* hist2, + unsigned int* partialBuf0, unsigned int* partialBuf1, unsigned int* partialBuf2, + bool cc20, cudaStream_t stream); static const func_t funcs[4][4] = { {0,0,0,0}, {0,0,0,0}, - {0,0,bgfg::calcDiffHistogram_gpu,bgfg::calcDiffHistogram_gpu}, - {0,0,bgfg::calcDiffHistogram_gpu,bgfg::calcDiffHistogram_gpu} + {0,0,fgd::calcDiffHistogram_gpu,fgd::calcDiffHistogram_gpu}, + {0,0,fgd::calcDiffHistogram_gpu,fgd::calcDiffHistogram_gpu} }; hist.create(3, 256, CV_32SC1); - histBuf.create(3, bgfg::PARTIAL_HISTOGRAM_COUNT * bgfg::HISTOGRAM_BIN_COUNT, CV_32SC1); + histBuf.create(3, fgd::PARTIAL_HISTOGRAM_COUNT * fgd::HISTOGRAM_BIN_COUNT, CV_32SC1); funcs[prevFrame.channels() - 1][curFrame.channels() - 1]( prevFrame, curFrame, hist.ptr(0), hist.ptr(1), hist.ptr(2), histBuf.ptr(0), histBuf.ptr(1), histBuf.ptr(2), - cv::gpu::deviceSupports(cv::gpu::FEATURE_SET_COMPUTE_20), 0); + deviceSupports(FEATURE_SET_COMPUTE_20), 0); } - void calcRelativeVariance(unsigned int hist[3 * 256], double relativeVariance[3][bgfg::HISTOGRAM_BIN_COUNT]) + void calcRelativeVariance(unsigned int hist[3 * 256], double relativeVariance[3][fgd::HISTOGRAM_BIN_COUNT]) { - std::memset(relativeVariance, 0, 3 * bgfg::HISTOGRAM_BIN_COUNT * sizeof(double)); + std::memset(relativeVariance, 0, 3 * fgd::HISTOGRAM_BIN_COUNT * sizeof(double)); - for (int thres = bgfg::HISTOGRAM_BIN_COUNT - 2; thres >= 0; --thres) + for (int thres = fgd::HISTOGRAM_BIN_COUNT - 2; thres >= 0; --thres) { - cv::Vec3d sum(0.0, 0.0, 0.0); - cv::Vec3d sqsum(0.0, 0.0, 0.0); - cv::Vec3i count(0, 0, 0); + Vec3d sum(0.0, 0.0, 0.0); + Vec3d sqsum(0.0, 0.0, 0.0); + Vec3i count(0, 0, 0); - for (int j = thres; j < bgfg::HISTOGRAM_BIN_COUNT; ++j) + for (int j = thres; j < fgd::HISTOGRAM_BIN_COUNT; ++j) { sum[0] += static_cast(j) * hist[j]; sqsum[0] += static_cast(j * j) * hist[j]; @@ -383,7 +204,7 @@ namespace count[1] = std::max(count[1], 1); count[2] = std::max(count[2], 1); - cv::Vec3d my( + Vec3d my( sum[0] / count[0], sum[1] / count[1], sum[2] / count[2] @@ -395,37 +216,39 @@ namespace } } - void calcDiffThreshMask(const cv::gpu::GpuMat& prevFrame, const cv::gpu::GpuMat& curFrame, cv::Vec3d bestThres, cv::gpu::GpuMat& changeMask) + void calcDiffThreshMask(const GpuMat& prevFrame, const GpuMat& curFrame, Vec3d bestThres, GpuMat& changeMask) { - typedef void (*func_t)(cv::gpu::PtrStepSzb prevFrame, cv::gpu::PtrStepSzb curFrame, uchar3 bestThres, cv::gpu::PtrStepSzb changeMask, cudaStream_t stream); + typedef void (*func_t)(PtrStepSzb prevFrame, PtrStepSzb curFrame, uchar3 bestThres, PtrStepSzb changeMask, cudaStream_t stream); static const func_t funcs[4][4] = { {0,0,0,0}, {0,0,0,0}, - {0,0,bgfg::calcDiffThreshMask_gpu,bgfg::calcDiffThreshMask_gpu}, - {0,0,bgfg::calcDiffThreshMask_gpu,bgfg::calcDiffThreshMask_gpu} + {0,0,fgd::calcDiffThreshMask_gpu,fgd::calcDiffThreshMask_gpu}, + {0,0,fgd::calcDiffThreshMask_gpu,fgd::calcDiffThreshMask_gpu} }; - changeMask.setTo(cv::Scalar::all(0)); + changeMask.setTo(Scalar::all(0)); - funcs[prevFrame.channels() - 1][curFrame.channels() - 1](prevFrame, curFrame, make_uchar3((uchar)bestThres[0], (uchar)bestThres[1], (uchar)bestThres[2]), changeMask, 0); + funcs[prevFrame.channels() - 1][curFrame.channels() - 1](prevFrame, curFrame, + make_uchar3((uchar)bestThres[0], (uchar)bestThres[1], (uchar)bestThres[2]), + changeMask, 0); } // performs change detection for Foreground detection algorithm - void changeDetection(const cv::gpu::GpuMat& prevFrame, const cv::gpu::GpuMat& curFrame, cv::gpu::GpuMat& changeMask, cv::gpu::GpuMat& hist, cv::gpu::GpuMat& histBuf) + void changeDetection(const GpuMat& prevFrame, const GpuMat& curFrame, GpuMat& changeMask, GpuMat& hist, GpuMat& histBuf) { calcDiffHistogram(prevFrame, curFrame, hist, histBuf); unsigned int histData[3 * 256]; - cv::Mat h_hist(3, 256, CV_32SC1, histData); + Mat h_hist(3, 256, CV_32SC1, histData); hist.download(h_hist); - double relativeVariance[3][bgfg::HISTOGRAM_BIN_COUNT]; + double relativeVariance[3][fgd::HISTOGRAM_BIN_COUNT]; calcRelativeVariance(histData, relativeVariance); // Find maximum: - cv::Vec3d bestThres(10.0, 10.0, 10.0); - for (int i = 0; i < bgfg::HISTOGRAM_BIN_COUNT; ++i) + Vec3d bestThres(10.0, 10.0, 10.0); + for (int i = 0; i < fgd::HISTOGRAM_BIN_COUNT; ++i) { bestThres[0] = std::max(bestThres[0], relativeVariance[0][i]); bestThres[1] = std::max(bestThres[1], relativeVariance[1][i]); @@ -441,12 +264,12 @@ namespace namespace { - int bgfgClassification(const cv::gpu::GpuMat& prevFrame, const cv::gpu::GpuMat& curFrame, - const cv::gpu::GpuMat& Ftd, const cv::gpu::GpuMat& Fbd, - cv::gpu::GpuMat& foreground, cv::gpu::GpuMat& countBuf, - const cv::gpu::FGDStatModel::Params& params, int out_cn) + int bgfgClassification(const GpuMat& prevFrame, const GpuMat& curFrame, + const GpuMat& Ftd, const GpuMat& Fbd, + GpuMat& foreground, GpuMat& countBuf, + const FGDParams& params, int out_cn) { - typedef void (*func_t)(cv::gpu::PtrStepSzb prevFrame, cv::gpu::PtrStepSzb curFrame, cv::gpu::PtrStepSzb Ftd, cv::gpu::PtrStepSzb Fbd, cv::gpu::PtrStepSzb foreground, + typedef void (*func_t)(PtrStepSzb prevFrame, PtrStepSzb curFrame, PtrStepSzb Ftd, PtrStepSzb Fbd, PtrStepSzb foreground, int deltaC, int deltaCC, float alpha2, int N1c, int N1cc, cudaStream_t stream); static const func_t funcs[4][4][4] = { @@ -458,24 +281,26 @@ namespace }, { {0,0,0,0}, {0,0,0,0}, - {0,0,bgfg::bgfgClassification_gpu,bgfg::bgfgClassification_gpu}, - {0,0,bgfg::bgfgClassification_gpu,bgfg::bgfgClassification_gpu} + {0,0,fgd::bgfgClassification_gpu,fgd::bgfgClassification_gpu}, + {0,0,fgd::bgfgClassification_gpu,fgd::bgfgClassification_gpu} }, { {0,0,0,0}, {0,0,0,0}, - {0,0,bgfg::bgfgClassification_gpu,bgfg::bgfgClassification_gpu}, - {0,0,bgfg::bgfgClassification_gpu,bgfg::bgfgClassification_gpu} + {0,0,fgd::bgfgClassification_gpu,fgd::bgfgClassification_gpu}, + {0,0,fgd::bgfgClassification_gpu,fgd::bgfgClassification_gpu} } }; const int deltaC = cvRound(params.delta * 256 / params.Lc); const int deltaCC = cvRound(params.delta * 256 / params.Lcc); - funcs[prevFrame.channels() - 1][curFrame.channels() - 1][out_cn - 1](prevFrame, curFrame, Ftd, Fbd, foreground, deltaC, deltaCC, params.alpha2, params.N1c, params.N1cc, 0); + funcs[prevFrame.channels() - 1][curFrame.channels() - 1][out_cn - 1](prevFrame, curFrame, Ftd, Fbd, foreground, + deltaC, deltaCC, params.alpha2, + params.N1c, params.N1cc, 0); - int count = cv::gpu::countNonZero(foreground, countBuf); + int count = gpu::countNonZero(foreground, countBuf); - cv::gpu::multiply(foreground, cv::Scalar::all(255), foreground); + gpu::multiply(foreground, Scalar::all(255), foreground); return count; } @@ -484,22 +309,24 @@ namespace ///////////////////////////////////////////////////////////////////////// // smoothForeground +#ifdef HAVE_OPENCV_GPUFILTERS + namespace { - void morphology(const cv::gpu::GpuMat& src, cv::gpu::GpuMat& dst, cv::gpu::GpuMat& filterBrd, int brd, cv::Ptr& filter, cv::Scalar brdVal) + void morphology(const GpuMat& src, GpuMat& dst, GpuMat& filterBrd, int brd, Ptr& filter, Scalar brdVal) { - cv::gpu::copyMakeBorder(src, filterBrd, brd, brd, brd, brd, cv::BORDER_CONSTANT, brdVal); - filter->apply(filterBrd(cv::Rect(brd, brd, src.cols, src.rows)), dst); + gpu::copyMakeBorder(src, filterBrd, brd, brd, brd, brd, BORDER_CONSTANT, brdVal); + filter->apply(filterBrd(Rect(brd, brd, src.cols, src.rows)), dst); } - void smoothForeground(cv::gpu::GpuMat& foreground, cv::gpu::GpuMat& filterBrd, cv::gpu::GpuMat& buf, - cv::Ptr& erodeFilter, cv::Ptr& dilateFilter, - const cv::gpu::FGDStatModel::Params& params) + void smoothForeground(GpuMat& foreground, GpuMat& filterBrd, GpuMat& buf, + Ptr& erodeFilter, Ptr& dilateFilter, + const FGDParams& params) { const int brd = params.perform_morphing; - const cv::Scalar erodeBrdVal = cv::Scalar::all(UCHAR_MAX); - const cv::Scalar dilateBrdVal = cv::Scalar::all(0); + const Scalar erodeBrdVal = Scalar::all(UCHAR_MAX); + const Scalar dilateBrdVal = Scalar::all(0); // MORPH_OPEN morphology(foreground, buf, filterBrd, brd, erodeFilter, erodeBrdVal); @@ -511,33 +338,35 @@ namespace } } +#endif + ///////////////////////////////////////////////////////////////////////// // findForegroundRegions namespace { - void seqToContours(CvSeq* _ccontours, CvMemStorage* storage, cv::OutputArrayOfArrays _contours) + void seqToContours(CvSeq* _ccontours, CvMemStorage* storage, OutputArrayOfArrays _contours) { - cv::Seq all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage)); + Seq all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage)); size_t total = all_contours.size(); _contours.create((int) total, 1, 0, -1, true); - cv::SeqIterator it = all_contours.begin(); + SeqIterator it = all_contours.begin(); for (size_t i = 0; i < total; ++i, ++it) { CvSeq* c = *it; ((CvContour*)c)->color = (int)i; _contours.create((int)c->total, 1, CV_32SC2, (int)i, true); - cv::Mat ci = _contours.getMat((int)i); + Mat ci = _contours.getMat((int)i); CV_Assert( ci.isContinuous() ); cvCvtSeqToArray(c, ci.data); } } - int findForegroundRegions(cv::gpu::GpuMat& d_foreground, cv::Mat& h_foreground, std::vector< std::vector >& foreground_regions, - CvMemStorage* storage, const cv::gpu::FGDStatModel::Params& params) + int findForegroundRegions(GpuMat& d_foreground, Mat& h_foreground, std::vector< std::vector >& foreground_regions, + CvMemStorage* storage, const FGDParams& params) { int region_count = 0; @@ -581,7 +410,7 @@ namespace seqToContours(first_seq, storage, foreground_regions); h_foreground.setTo(0); - cv::drawContours(h_foreground, foreground_regions, -1, cv::Scalar::all(255), -1); + drawContours(h_foreground, foreground_regions, -1, Scalar::all(255), -1); d_foreground.upload(h_foreground); @@ -594,12 +423,12 @@ namespace namespace { - void updateBackgroundModel(const cv::gpu::GpuMat& prevFrame, const cv::gpu::GpuMat& curFrame, const cv::gpu::GpuMat& Ftd, const cv::gpu::GpuMat& Fbd, - const cv::gpu::GpuMat& foreground, cv::gpu::GpuMat& background, - const cv::gpu::FGDStatModel::Params& params) + void updateBackgroundModel(const GpuMat& prevFrame, const GpuMat& curFrame, const GpuMat& Ftd, const GpuMat& Fbd, + const GpuMat& foreground, GpuMat& background, + const FGDParams& params) { - typedef void (*func_t)(cv::gpu::PtrStepSzb prevFrame, cv::gpu::PtrStepSzb curFrame, cv::gpu::PtrStepSzb Ftd, cv::gpu::PtrStepSzb Fbd, - cv::gpu::PtrStepSzb foreground, cv::gpu::PtrStepSzb background, + typedef void (*func_t)(PtrStepSzb prevFrame, PtrStepSzb curFrame, PtrStepSzb Ftd, PtrStepSzb Fbd, + PtrStepSzb foreground, PtrStepSzb background, int deltaC, int deltaCC, float alpha1, float alpha2, float alpha3, int N1c, int N1cc, int N2c, int N2cc, float T, cudaStream_t stream); static const func_t funcs[4][4][4] = { @@ -611,13 +440,13 @@ namespace }, { {0,0,0,0}, {0,0,0,0}, - {0,0,bgfg::updateBackgroundModel_gpu,bgfg::updateBackgroundModel_gpu}, - {0,0,bgfg::updateBackgroundModel_gpu,bgfg::updateBackgroundModel_gpu} + {0,0,fgd::updateBackgroundModel_gpu,fgd::updateBackgroundModel_gpu}, + {0,0,fgd::updateBackgroundModel_gpu,fgd::updateBackgroundModel_gpu} }, { {0,0,0,0}, {0,0,0,0}, - {0,0,bgfg::updateBackgroundModel_gpu,bgfg::updateBackgroundModel_gpu}, - {0,0,bgfg::updateBackgroundModel_gpu,bgfg::updateBackgroundModel_gpu} + {0,0,fgd::updateBackgroundModel_gpu,fgd::updateBackgroundModel_gpu}, + {0,0,fgd::updateBackgroundModel_gpu,fgd::updateBackgroundModel_gpu} } }; @@ -626,126 +455,277 @@ namespace funcs[prevFrame.channels() - 1][curFrame.channels() - 1][background.channels() - 1]( prevFrame, curFrame, Ftd, Fbd, foreground, background, - deltaC, deltaCC, params.alpha1, params.alpha2, params.alpha3, params.N1c, params.N1cc, params.N2c, params.N2cc, params.T, + deltaC, deltaCC, params.alpha1, params.alpha2, params.alpha3, + params.N1c, params.N1cc, params.N2c, params.N2cc, params.T, 0); } } -///////////////////////////////////////////////////////////////////////// -// Impl::update - -int cv::gpu::FGDStatModel::Impl::update(const cv::gpu::GpuMat& curFrame) -{ - CV_Assert(curFrame.type() == CV_8UC3 || curFrame.type() == CV_8UC4); - CV_Assert(curFrame.size() == prevFrame_.size()); - - cvClearMemStorage(storage_); - foreground_regions_.clear(); - foreground_.setTo(cv::Scalar::all(0)); - - changeDetection(prevFrame_, curFrame, Ftd_, hist_, histBuf_); - changeDetection(background_, curFrame, Fbd_, hist_, histBuf_); - - int FG_pixels_count = bgfgClassification(prevFrame_, curFrame, Ftd_, Fbd_, foreground_, countBuf_, params_, out_cn_); - - if (params_.perform_morphing > 0) - smoothForeground(foreground_, filterBrd_, buf_, erodeFilter_, dilateFilter_, params_); - - int region_count = 0; - if (params_.minArea > 0 || params_.is_obj_without_holes) - region_count = findForegroundRegions(foreground_, h_foreground_, foreground_regions_, storage_, params_); - - // Check ALL BG update condition: - const double BGFG_FGD_BG_UPDATE_TRESH = 0.5; - if (static_cast(FG_pixels_count) / Ftd_.size().area() > BGFG_FGD_BG_UPDATE_TRESH) - stat_.setTrained(); - - updateBackgroundModel(prevFrame_, curFrame, Ftd_, Fbd_, foreground_, background_, params_); - - copyChannels(curFrame, prevFrame_); - - return region_count; -} namespace { - // Default parameters of foreground detection algorithm: - const int BGFG_FGD_LC = 128; - const int BGFG_FGD_N1C = 15; - const int BGFG_FGD_N2C = 25; + class BGPixelStat + { + public: + void create(Size size, const FGDParams& params); - const int BGFG_FGD_LCC = 64; - const int BGFG_FGD_N1CC = 25; - const int BGFG_FGD_N2CC = 40; + void setTrained(); - // Background reference image update parameter: - const float BGFG_FGD_ALPHA_1 = 0.1f; + operator fgd::BGPixelStat(); - // stat model update parameter - // 0.002f ~ 1K frame(~45sec), 0.005 ~ 18sec (if 25fps and absolutely static BG) - const float BGFG_FGD_ALPHA_2 = 0.005f; + private: + GpuMat Pbc_; + GpuMat Pbcc_; + GpuMat is_trained_st_model_; + GpuMat is_trained_dyn_model_; - // start value for alpha parameter (to fast initiate statistic model) - const float BGFG_FGD_ALPHA_3 = 0.1f; + GpuMat ctable_Pv_; + GpuMat ctable_Pvb_; + GpuMat ctable_v_; - const float BGFG_FGD_DELTA = 2.0f; + GpuMat cctable_Pv_; + GpuMat cctable_Pvb_; + GpuMat cctable_v1_; + GpuMat cctable_v2_; + }; - const float BGFG_FGD_T = 0.9f; + void BGPixelStat::create(Size size, const FGDParams& params) + { + gpu::ensureSizeIsEnough(size, CV_32FC1, Pbc_); + Pbc_.setTo(Scalar::all(0)); - const float BGFG_FGD_MINAREA= 15.0f; + gpu::ensureSizeIsEnough(size, CV_32FC1, Pbcc_); + Pbcc_.setTo(Scalar::all(0)); + + gpu::ensureSizeIsEnough(size, CV_8UC1, is_trained_st_model_); + is_trained_st_model_.setTo(Scalar::all(0)); + + gpu::ensureSizeIsEnough(size, CV_8UC1, is_trained_dyn_model_); + is_trained_dyn_model_.setTo(Scalar::all(0)); + + gpu::ensureSizeIsEnough(params.N2c * size.height, size.width, CV_32FC1, ctable_Pv_); + ctable_Pv_.setTo(Scalar::all(0)); + + gpu::ensureSizeIsEnough(params.N2c * size.height, size.width, CV_32FC1, ctable_Pvb_); + ctable_Pvb_.setTo(Scalar::all(0)); + + gpu::ensureSizeIsEnough(params.N2c * size.height, size.width, CV_8UC4, ctable_v_); + ctable_v_.setTo(Scalar::all(0)); + + gpu::ensureSizeIsEnough(params.N2cc * size.height, size.width, CV_32FC1, cctable_Pv_); + cctable_Pv_.setTo(Scalar::all(0)); + + gpu::ensureSizeIsEnough(params.N2cc * size.height, size.width, CV_32FC1, cctable_Pvb_); + cctable_Pvb_.setTo(Scalar::all(0)); + + gpu::ensureSizeIsEnough(params.N2cc * size.height, size.width, CV_8UC4, cctable_v1_); + cctable_v1_.setTo(Scalar::all(0)); + + gpu::ensureSizeIsEnough(params.N2cc * size.height, size.width, CV_8UC4, cctable_v2_); + cctable_v2_.setTo(Scalar::all(0)); + } + + void BGPixelStat::setTrained() + { + is_trained_st_model_.setTo(Scalar::all(1)); + is_trained_dyn_model_.setTo(Scalar::all(1)); + } + + BGPixelStat::operator fgd::BGPixelStat() + { + fgd::BGPixelStat stat; + + stat.rows_ = Pbc_.rows; + + stat.Pbc_data_ = Pbc_.data; + stat.Pbc_step_ = Pbc_.step; + + stat.Pbcc_data_ = Pbcc_.data; + stat.Pbcc_step_ = Pbcc_.step; + + stat.is_trained_st_model_data_ = is_trained_st_model_.data; + stat.is_trained_st_model_step_ = is_trained_st_model_.step; + + stat.is_trained_dyn_model_data_ = is_trained_dyn_model_.data; + stat.is_trained_dyn_model_step_ = is_trained_dyn_model_.step; + + stat.ctable_Pv_data_ = ctable_Pv_.data; + stat.ctable_Pv_step_ = ctable_Pv_.step; + + stat.ctable_Pvb_data_ = ctable_Pvb_.data; + stat.ctable_Pvb_step_ = ctable_Pvb_.step; + + stat.ctable_v_data_ = ctable_v_.data; + stat.ctable_v_step_ = ctable_v_.step; + + stat.cctable_Pv_data_ = cctable_Pv_.data; + stat.cctable_Pv_step_ = cctable_Pv_.step; + + stat.cctable_Pvb_data_ = cctable_Pvb_.data; + stat.cctable_Pvb_step_ = cctable_Pvb_.step; + + stat.cctable_v1_data_ = cctable_v1_.data; + stat.cctable_v1_step_ = cctable_v1_.step; + + stat.cctable_v2_data_ = cctable_v2_.data; + stat.cctable_v2_step_ = cctable_v2_.step; + + return stat; + } + + class FGDImpl : public gpu::BackgroundSubtractorFGD + { + public: + explicit FGDImpl(const FGDParams& params); + ~FGDImpl(); + + void apply(InputArray image, OutputArray fgmask, double learningRate=-1); + + void getBackgroundImage(OutputArray backgroundImage) const; + + void getForegroundRegions(OutputArrayOfArrays foreground_regions); + + private: + void initialize(const GpuMat& firstFrame); + + FGDParams params_; + Size frameSize_; + + GpuMat background_; + GpuMat foreground_; + std::vector< std::vector > foreground_regions_; + + Mat h_foreground_; + + GpuMat prevFrame_; + GpuMat Ftd_; + GpuMat Fbd_; + BGPixelStat stat_; + + GpuMat hist_; + GpuMat histBuf_; + + GpuMat countBuf_; + + GpuMat buf_; + GpuMat filterBrd_; + +#ifdef HAVE_OPENCV_GPUFILTERS + Ptr dilateFilter_; + Ptr erodeFilter_; +#endif + + CvMemStorage* storage_; + }; + + FGDImpl::FGDImpl(const FGDParams& params) : params_(params), frameSize_(0, 0) + { + storage_ = cvCreateMemStorage(); + CV_Assert( storage_ != 0 ); + } + + FGDImpl::~FGDImpl() + { + cvReleaseMemStorage(&storage_); + } + + void FGDImpl::apply(InputArray _frame, OutputArray fgmask, double) + { + GpuMat curFrame = _frame.getGpuMat(); + + if (curFrame.size() != frameSize_) + { + initialize(curFrame); + return; + } + + CV_Assert( curFrame.type() == CV_8UC3 || curFrame.type() == CV_8UC4 ); + CV_Assert( curFrame.size() == prevFrame_.size() ); + + cvClearMemStorage(storage_); + foreground_regions_.clear(); + foreground_.setTo(Scalar::all(0)); + + changeDetection(prevFrame_, curFrame, Ftd_, hist_, histBuf_); + changeDetection(background_, curFrame, Fbd_, hist_, histBuf_); + + int FG_pixels_count = bgfgClassification(prevFrame_, curFrame, Ftd_, Fbd_, foreground_, countBuf_, params_, 4); + +#ifdef HAVE_OPENCV_GPUFILTERS + if (params_.perform_morphing > 0) + smoothForeground(foreground_, filterBrd_, buf_, erodeFilter_, dilateFilter_, params_); +#endif + + if (params_.minArea > 0 || params_.is_obj_without_holes) + findForegroundRegions(foreground_, h_foreground_, foreground_regions_, storage_, params_); + + // Check ALL BG update condition: + const double BGFG_FGD_BG_UPDATE_TRESH = 0.5; + if (static_cast(FG_pixels_count) / Ftd_.size().area() > BGFG_FGD_BG_UPDATE_TRESH) + stat_.setTrained(); + + updateBackgroundModel(prevFrame_, curFrame, Ftd_, Fbd_, foreground_, background_, params_); + + copyChannels(curFrame, prevFrame_, 4); + + foreground_.copyTo(fgmask); + } + + void FGDImpl::getBackgroundImage(OutputArray backgroundImage) const + { + gpu::cvtColor(background_, backgroundImage, COLOR_BGRA2BGR); + } + + void FGDImpl::getForegroundRegions(OutputArrayOfArrays dst) + { + size_t total = foreground_regions_.size(); + + dst.create((int) total, 1, 0, -1, true); + + for (size_t i = 0; i < total; ++i) + { + std::vector& c = foreground_regions_[i]; + + dst.create((int) c.size(), 1, CV_32SC2, (int) i, true); + Mat ci = dst.getMat((int) i); + + Mat(ci.size(), ci.type(), &c[0]).copyTo(ci); + } + } + + void FGDImpl::initialize(const GpuMat& firstFrame) + { + CV_Assert( firstFrame.type() == CV_8UC3 || firstFrame.type() == CV_8UC4 ); + + frameSize_ = firstFrame.size(); + + gpu::ensureSizeIsEnough(firstFrame.size(), CV_8UC1, foreground_); + + copyChannels(firstFrame, background_, 4); + copyChannels(firstFrame, prevFrame_, 4); + + gpu::ensureSizeIsEnough(firstFrame.size(), CV_8UC1, Ftd_); + gpu::ensureSizeIsEnough(firstFrame.size(), CV_8UC1, Fbd_); + + stat_.create(firstFrame.size(), params_); + fgd::setBGPixelStat(stat_); + +#ifdef HAVE_OPENCV_GPUFILTERS + if (params_.perform_morphing > 0) + { + Mat kernel = getStructuringElement(MORPH_RECT, Size(1 + params_.perform_morphing * 2, 1 + params_.perform_morphing * 2)); + Point anchor(params_.perform_morphing, params_.perform_morphing); + + dilateFilter_ = gpu::createMorphologyFilter(MORPH_DILATE, CV_8UC1, kernel, anchor); + erodeFilter_ = gpu::createMorphologyFilter(MORPH_ERODE, CV_8UC1, kernel, anchor); + } +#endif + } } -cv::gpu::FGDStatModel::Params::Params() +Ptr cv::gpu::createBackgroundSubtractorFGD(const FGDParams& params) { - Lc = BGFG_FGD_LC; - N1c = BGFG_FGD_N1C; - N2c = BGFG_FGD_N2C; - - Lcc = BGFG_FGD_LCC; - N1cc = BGFG_FGD_N1CC; - N2cc = BGFG_FGD_N2CC; - - delta = BGFG_FGD_DELTA; - - alpha1 = BGFG_FGD_ALPHA_1; - alpha2 = BGFG_FGD_ALPHA_2; - alpha3 = BGFG_FGD_ALPHA_3; - - T = BGFG_FGD_T; - minArea = BGFG_FGD_MINAREA; - - is_obj_without_holes = true; - perform_morphing = 1; -} - -cv::gpu::FGDStatModel::FGDStatModel(int out_cn) -{ - impl_.reset(new Impl(background, foreground, foreground_regions, out_cn)); -} - -cv::gpu::FGDStatModel::FGDStatModel(const cv::gpu::GpuMat& firstFrame, const Params& params, int out_cn) -{ - impl_.reset(new Impl(background, foreground, foreground_regions, out_cn)); - create(firstFrame, params); -} - -cv::gpu::FGDStatModel::~FGDStatModel() -{ -} - -void cv::gpu::FGDStatModel::create(const cv::gpu::GpuMat& firstFrame, const Params& params) -{ - impl_->create(firstFrame, params); -} - -void cv::gpu::FGDStatModel::release() -{ - impl_->release(); -} - -int cv::gpu::FGDStatModel::update(const cv::gpu::GpuMat& curFrame) -{ - return impl_->update(curFrame); + return makePtr(params); } #endif // HAVE_CUDA diff --git a/modules/gpubgsegm/src/gmg.cpp b/modules/gpubgsegm/src/gmg.cpp index b97f0836f..f8650b242 100644 --- a/modules/gpubgsegm/src/gmg.cpp +++ b/modules/gpubgsegm/src/gmg.cpp @@ -42,17 +42,17 @@ #include "precomp.hpp" +using namespace cv; +using namespace cv::gpu; + #if !defined HAVE_CUDA || defined(CUDA_DISABLER) -cv::gpu::GMG_GPU::GMG_GPU() { throw_no_cuda(); } -void cv::gpu::GMG_GPU::initialize(cv::Size, float, float) { throw_no_cuda(); } -void cv::gpu::GMG_GPU::operator ()(const cv::gpu::GpuMat&, cv::gpu::GpuMat&, float, cv::gpu::Stream&) { throw_no_cuda(); } -void cv::gpu::GMG_GPU::release() {} +Ptr cv::gpu::createBackgroundSubtractorGMG(int, double) { throw_no_cuda(); return Ptr(); } #else namespace cv { namespace gpu { namespace cudev { - namespace bgfg_gmg + namespace gmg { void loadConstants(int width, int height, float minVal, float maxVal, int quantizationLevels, float backgroundPrior, float decisionThreshold, int maxFeatures, int numInitializationFrames); @@ -63,103 +63,215 @@ namespace cv { namespace gpu { namespace cudev { } }}} -cv::gpu::GMG_GPU::GMG_GPU() +namespace { - 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::cudev::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(CV_8UC1, -1, 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::cudev::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] = + class GMGImpl : public gpu::BackgroundSubtractorGMG { - {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} + public: + GMGImpl(int initializationFrames, double decisionThreshold); + + void apply(InputArray image, OutputArray fgmask, double learningRate=-1); + void apply(InputArray image, OutputArray fgmask, double learningRate, Stream& stream); + + void getBackgroundImage(OutputArray backgroundImage) const; + + int getMaxFeatures() const { return maxFeatures_; } + void setMaxFeatures(int maxFeatures) { maxFeatures_ = maxFeatures; } + + double getDefaultLearningRate() const { return learningRate_; } + void setDefaultLearningRate(double lr) { learningRate_ = (float) lr; } + + int getNumFrames() const { return numInitializationFrames_; } + void setNumFrames(int nframes) { numInitializationFrames_ = nframes; } + + int getQuantizationLevels() const { return quantizationLevels_; } + void setQuantizationLevels(int nlevels) { quantizationLevels_ = nlevels; } + + double getBackgroundPrior() const { return backgroundPrior_; } + void setBackgroundPrior(double bgprior) { backgroundPrior_ = (float) bgprior; } + + int getSmoothingRadius() const { return smoothingRadius_; } + void setSmoothingRadius(int radius) { smoothingRadius_ = radius; } + + double getDecisionThreshold() const { return decisionThreshold_; } + void setDecisionThreshold(double thresh) { decisionThreshold_ = (float) thresh; } + + bool getUpdateBackgroundModel() const { return updateBackgroundModel_; } + void setUpdateBackgroundModel(bool update) { updateBackgroundModel_ = update; } + + double getMinVal() const { return minVal_; } + void setMinVal(double val) { minVal_ = (float) val; } + + double getMaxVal() const { return maxVal_; } + void setMaxVal(double val) { maxVal_ = (float) val; } + + private: + void initialize(Size frameSize, float min, float max); + + //! 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_; + + //! Smoothing radius, in pixels, for cleaning up FG image. + int smoothingRadius_; + + //! Value above which pixel is determined to be FG. + float decisionThreshold_; + + //! Perform background model update. + bool updateBackgroundModel_; + + float minVal_, maxVal_; + + Size frameSize_; + int frameNum_; + + GpuMat nfeatures_; + GpuMat colors_; + GpuMat weights_; + +#if defined(HAVE_OPENCV_GPUFILTERS) && defined(HAVE_OPENCV_GPUARITHM) + Ptr boxFilter_; + GpuMat buf_; +#endif }; - 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) + GMGImpl::GMGImpl(int initializationFrames, double decisionThreshold) { - CV_Assert(newLearningRate >= 0.0f && newLearningRate <= 1.0f); - learningRate = newLearningRate; + maxFeatures_ = 64; + learningRate_ = 0.025f; + numInitializationFrames_ = initializationFrames; + quantizationLevels_ = 16; + backgroundPrior_ = 0.8f; + decisionThreshold_ = (float) decisionThreshold; + smoothingRadius_ = 7; + updateBackgroundModel_ = true; + minVal_ = maxVal_ = 0; } - 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); - fgmask.setTo(cv::Scalar::all(0), stream); - - funcs[frame.depth()][frame.channels() - 1](frame, fgmask, colors_, weights_, nfeatures_, frameNum_, learningRate, updateBackgroundModel, cv::gpu::StreamAccessor::getStream(stream)); - - // medianBlur - if (smoothingRadius > 0) + void GMGImpl::apply(InputArray image, OutputArray fgmask, double learningRate) { - boxFilter_->apply(fgmask, buf_, 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); + apply(image, fgmask, learningRate, Stream::Null()); } - // keep track of how many frames we have processed - ++frameNum_; + void GMGImpl::apply(InputArray _frame, OutputArray _fgmask, double newLearningRate, Stream& stream) + { + using namespace cv::gpu::cudev::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} + }; + + GpuMat frame = _frame.getGpuMat(); + + 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.0) + { + CV_Assert( newLearningRate >= 0.0 && newLearningRate <= 1.0 ); + learningRate_ = (float) newLearningRate; + } + + if (frame.size() != frameSize_) + { + double minVal = minVal_; + double maxVal = maxVal_; + + if (minVal_ == 0 && maxVal_ == 0) + { + minVal = 0; + maxVal = frame.depth() == CV_8U ? 255.0 : frame.depth() == CV_16U ? std::numeric_limits::max() : 1.0; + } + + initialize(frame.size(), (float) minVal, (float) maxVal); + } + + _fgmask.create(frameSize_, CV_8UC1); + GpuMat fgmask = _fgmask.getGpuMat(); + + fgmask.setTo(Scalar::all(0), stream); + + funcs[frame.depth()][frame.channels() - 1](frame, fgmask, colors_, weights_, nfeatures_, frameNum_, + learningRate_, updateBackgroundModel_, StreamAccessor::getStream(stream)); + +#if defined(HAVE_OPENCV_GPUFILTERS) && defined(HAVE_OPENCV_GPUARITHM) + // medianBlur + if (smoothingRadius_ > 0) + { + boxFilter_->apply(fgmask, buf_, stream); + const int minCount = (smoothingRadius_ * smoothingRadius_ + 1) / 2; + const double thresh = 255.0 * minCount / (smoothingRadius_ * smoothingRadius_); + gpu::threshold(buf_, fgmask, thresh, 255.0, THRESH_BINARY, stream); + } +#endif + + // keep track of how many frames we have processed + ++frameNum_; + } + + void GMGImpl::getBackgroundImage(OutputArray backgroundImage) const + { + (void) backgroundImage; + CV_Error(Error::StsNotImplemented, "Not implemented"); + } + + void GMGImpl::initialize(Size frameSize, float min, float max) + { + using namespace cv::gpu::cudev::gmg; + + 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; + CV_Assert( minVal_ < maxVal_ ); + + 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(Scalar::all(0)); + +#if defined(HAVE_OPENCV_GPUFILTERS) && defined(HAVE_OPENCV_GPUARITHM) + if (smoothingRadius_ > 0) + boxFilter_ = gpu::createBoxFilter(CV_8UC1, -1, Size(smoothingRadius_, smoothingRadius_)); +#endif + + loadConstants(frameSize_.width, frameSize_.height, minVal_, maxVal_, + quantizationLevels_, backgroundPrior_, decisionThreshold_, maxFeatures_, numInitializationFrames_); + } } -void cv::gpu::GMG_GPU::release() +Ptr cv::gpu::createBackgroundSubtractorGMG(int initializationFrames, double decisionThreshold) { - frameSize_ = Size(); - - nfeatures_.release(); - colors_.release(); - weights_.release(); - boxFilter_.release(); - buf_.release(); + return makePtr(initializationFrames, decisionThreshold); } #endif diff --git a/modules/gpubgsegm/src/mog.cpp b/modules/gpubgsegm/src/mog.cpp index 22b31074f..12e5b3230 100644 --- a/modules/gpubgsegm/src/mog.cpp +++ b/modules/gpubgsegm/src/mog.cpp @@ -42,19 +42,12 @@ #include "precomp.hpp" +using namespace cv; +using namespace cv::gpu; + #if !defined HAVE_CUDA || defined(CUDA_DISABLER) -cv::gpu::MOG_GPU::MOG_GPU(int) { throw_no_cuda(); } -void cv::gpu::MOG_GPU::initialize(cv::Size, int) { throw_no_cuda(); } -void cv::gpu::MOG_GPU::operator()(const cv::gpu::GpuMat&, cv::gpu::GpuMat&, float, Stream&) { throw_no_cuda(); } -void cv::gpu::MOG_GPU::getBackgroundImage(GpuMat&, Stream&) const { throw_no_cuda(); } -void cv::gpu::MOG_GPU::release() {} - -cv::gpu::MOG2_GPU::MOG2_GPU(int) { throw_no_cuda(); } -void cv::gpu::MOG2_GPU::initialize(cv::Size, int) { throw_no_cuda(); } -void cv::gpu::MOG2_GPU::operator()(const GpuMat&, GpuMat&, float, Stream&) { throw_no_cuda(); } -void cv::gpu::MOG2_GPU::getBackgroundImage(GpuMat&, Stream&) const { throw_no_cuda(); } -void cv::gpu::MOG2_GPU::release() {} +Ptr cv::gpu::createBackgroundSubtractorMOG(int, int, double, double) { throw_no_cuda(); return Ptr(); } #else @@ -66,14 +59,10 @@ namespace cv { namespace gpu { namespace cudev 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 +namespace { const int defaultNMixtures = 5; const int defaultHistory = 200; @@ -81,199 +70,140 @@ namespace mog const float defaultVarThreshold = 2.5f * 2.5f; const float defaultNoiseSigma = 30.0f * 0.5f; const float defaultInitialWeight = 0.05f; + + class MOGImpl : public gpu::BackgroundSubtractorMOG + { + public: + MOGImpl(int history, int nmixtures, double backgroundRatio, double noiseSigma); + + void apply(InputArray image, OutputArray fgmask, double learningRate=-1); + void apply(InputArray image, OutputArray fgmask, double learningRate, Stream& stream); + + void getBackgroundImage(OutputArray backgroundImage) const; + void getBackgroundImage(OutputArray backgroundImage, Stream& stream) const; + + int getHistory() const { return history_; } + void setHistory(int nframes) { history_ = nframes; } + + int getNMixtures() const { return nmixtures_; } + void setNMixtures(int nmix) { nmixtures_ = nmix; } + + double getBackgroundRatio() const { return backgroundRatio_; } + void setBackgroundRatio(double backgroundRatio) { backgroundRatio_ = (float) backgroundRatio; } + + double getNoiseSigma() const { return noiseSigma_; } + void setNoiseSigma(double noiseSigma) { noiseSigma_ = (float) noiseSigma; } + + private: + //! re-initiaization method + void initialize(Size frameSize, int frameType); + + int history_; + int nmixtures_; + float backgroundRatio_; + float noiseSigma_; + + float varThreshold_; + + Size frameSize_; + int frameType_; + int nframes_; + + GpuMat weight_; + GpuMat sortKey_; + GpuMat mean_; + GpuMat var_; + }; + + MOGImpl::MOGImpl(int history, int nmixtures, double backgroundRatio, double noiseSigma) : + frameSize_(0, 0), frameType_(0), nframes_(0) + { + history_ = history > 0 ? history : defaultHistory; + nmixtures_ = std::min(nmixtures > 0 ? nmixtures : defaultNMixtures, 8); + backgroundRatio_ = backgroundRatio > 0 ? (float) backgroundRatio : defaultBackgroundRatio; + noiseSigma_ = noiseSigma > 0 ? (float) noiseSigma : defaultNoiseSigma; + + varThreshold_ = defaultVarThreshold; + } + + void MOGImpl::apply(InputArray image, OutputArray fgmask, double learningRate) + { + apply(image, fgmask, learningRate, Stream::Null()); + } + + void MOGImpl::apply(InputArray _frame, OutputArray _fgmask, double learningRate, Stream& stream) + { + using namespace cv::gpu::cudev::mog; + + GpuMat frame = _frame.getGpuMat(); + + 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); + GpuMat fgmask = _fgmask.getGpuMat(); + + ++nframes_; + learningRate = learningRate >= 0 && nframes_ > 1 ? learningRate : 1.0 / std::min(nframes_, history_); + CV_Assert( learningRate >= 0 ); + + mog_gpu(frame, ch, fgmask, weight_, sortKey_, mean_, var_, nmixtures_, + varThreshold_, (float) learningRate, backgroundRatio_, noiseSigma_, + StreamAccessor::getStream(stream)); + } + + void MOGImpl::getBackgroundImage(OutputArray backgroundImage) const + { + getBackgroundImage(backgroundImage, Stream::Null()); + } + + void MOGImpl::getBackgroundImage(OutputArray _backgroundImage, Stream& stream) const + { + using namespace cv::gpu::cudev::mog; + + _backgroundImage.create(frameSize_, frameType_); + GpuMat backgroundImage = _backgroundImage.getGpuMat(); + + getBackgroundImage_gpu(backgroundImage.channels(), weight_, mean_, backgroundImage, nmixtures_, backgroundRatio_, StreamAccessor::getStream(stream)); + } + + void MOGImpl::initialize(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; + } } -cv::gpu::MOG_GPU::MOG_GPU(int nmixtures) : - frameSize_(0, 0), frameType_(0), nframes_(0) +Ptr cv::gpu::createBackgroundSubtractorMOG(int history, int nmixtures, double backgroundRatio, double noiseSigma) { - 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::cudev::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::cudev::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::cudev::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::cudev::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::cudev::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(); + return makePtr(history, nmixtures, backgroundRatio, noiseSigma); } #endif diff --git a/modules/gpubgsegm/src/mog2.cpp b/modules/gpubgsegm/src/mog2.cpp new file mode 100644 index 000000000..5bfb5a1c4 --- /dev/null +++ b/modules/gpubgsegm/src/mog2.cpp @@ -0,0 +1,253 @@ +/*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; + +#if !defined HAVE_CUDA || defined(CUDA_DISABLER) + +Ptr cv::gpu::createBackgroundSubtractorMOG2(int, double, bool) { throw_no_cuda(); return Ptr(); } + +#else + +namespace cv { namespace gpu { namespace cudev +{ + namespace mog2 + { + 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 +{ + // 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 defaultCT = 0.05f; // complexity reduction prior constant 0 - no reduction of number of components + const unsigned char defaultShadowValue = 127; // value to use in the segmentation mask for shadows, set 0 not to do shadow detection + const float defaultShadowThreshold = 0.5f; // Tau - shadow threshold, see the paper for explanation + + class MOG2Impl : public gpu::BackgroundSubtractorMOG2 + { + public: + MOG2Impl(int history, double varThreshold, bool detectShadows); + + void apply(InputArray image, OutputArray fgmask, double learningRate=-1); + void apply(InputArray image, OutputArray fgmask, double learningRate, Stream& stream); + + void getBackgroundImage(OutputArray backgroundImage) const; + void getBackgroundImage(OutputArray backgroundImage, Stream& stream) const; + + int getHistory() const { return history_; } + void setHistory(int history) { history_ = history; } + + int getNMixtures() const { return nmixtures_; } + void setNMixtures(int nmixtures) { nmixtures_ = nmixtures; } + + double getBackgroundRatio() const { return backgroundRatio_; } + void setBackgroundRatio(double ratio) { backgroundRatio_ = (float) ratio; } + + double getVarThreshold() const { return varThreshold_; } + void setVarThreshold(double varThreshold) { varThreshold_ = (float) varThreshold; } + + double getVarThresholdGen() const { return varThresholdGen_; } + void setVarThresholdGen(double varThresholdGen) { varThresholdGen_ = (float) varThresholdGen; } + + double getVarInit() const { return varInit_; } + void setVarInit(double varInit) { varInit_ = (float) varInit; } + + double getVarMin() const { return varMin_; } + void setVarMin(double varMin) { varMin_ = (float) varMin; } + + double getVarMax() const { return varMax_; } + void setVarMax(double varMax) { varMax_ = (float) varMax; } + + double getComplexityReductionThreshold() const { return ct_; } + void setComplexityReductionThreshold(double ct) { ct_ = (float) ct; } + + bool getDetectShadows() const { return detectShadows_; } + void setDetectShadows(bool detectShadows) { detectShadows_ = detectShadows; } + + int getShadowValue() const { return shadowValue_; } + void setShadowValue(int value) { shadowValue_ = (uchar) value; } + + double getShadowThreshold() const { return shadowThreshold_; } + void setShadowThreshold(double threshold) { shadowThreshold_ = (float) threshold; } + + private: + void initialize(Size frameSize, int frameType); + + int history_; + int nmixtures_; + float backgroundRatio_; + float varThreshold_; + float varThresholdGen_; + float varInit_; + float varMin_; + float varMax_; + float ct_; + bool detectShadows_; + uchar shadowValue_; + float shadowThreshold_; + + Size frameSize_; + int frameType_; + int nframes_; + + GpuMat weight_; + GpuMat variance_; + GpuMat mean_; + + //keep track of number of modes per pixel + GpuMat bgmodelUsedModes_; + }; + + MOG2Impl::MOG2Impl(int history, double varThreshold, bool detectShadows) : + frameSize_(0, 0), frameType_(0), nframes_(0) + { + history_ = history > 0 ? history : defaultHistory; + varThreshold_ = varThreshold > 0 ? (float) varThreshold : defaultVarThreshold; + detectShadows_ = detectShadows; + + nmixtures_ = defaultNMixtures; + backgroundRatio_ = defaultBackgroundRatio; + varInit_ = defaultVarInit; + varMax_ = defaultVarMax; + varMin_ = defaultVarMin; + varThresholdGen_ = defaultVarThresholdGen; + ct_ = defaultCT; + shadowValue_ = defaultShadowValue; + shadowThreshold_ = defaultShadowThreshold; + } + + void MOG2Impl::apply(InputArray image, OutputArray fgmask, double learningRate) + { + apply(image, fgmask, learningRate, Stream::Null()); + } + + void MOG2Impl::apply(InputArray _frame, OutputArray _fgmask, double learningRate, Stream& stream) + { + using namespace cv::gpu::cudev::mog2; + + GpuMat frame = _frame.getGpuMat(); + + 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); + GpuMat fgmask = _fgmask.getGpuMat(); + + fgmask.setTo(Scalar::all(0), stream); + + ++nframes_; + learningRate = learningRate >= 0 && nframes_ > 1 ? learningRate : 1.0 / std::min(2 * nframes_, history_); + CV_Assert( learningRate >= 0 ); + + mog2_gpu(frame, frame.channels(), fgmask, bgmodelUsedModes_, weight_, variance_, mean_, + (float) learningRate, static_cast(-learningRate * ct_), detectShadows_, StreamAccessor::getStream(stream)); + } + + void MOG2Impl::getBackgroundImage(OutputArray backgroundImage) const + { + getBackgroundImage(backgroundImage, Stream::Null()); + } + + void MOG2Impl::getBackgroundImage(OutputArray _backgroundImage, Stream& stream) const + { + using namespace cv::gpu::cudev::mog2; + + _backgroundImage.create(frameSize_, frameType_); + GpuMat backgroundImage = _backgroundImage.getGpuMat(); + + getBackgroundImage2_gpu(backgroundImage.channels(), bgmodelUsedModes_, weight_, mean_, backgroundImage, StreamAccessor::getStream(stream)); + } + + void MOG2Impl::initialize(cv::Size frameSize, int frameType) + { + using namespace cv::gpu::cudev::mog2; + + 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(Scalar::all(0)); + + loadConstants(nmixtures_, varThreshold_, backgroundRatio_, varThresholdGen_, varInit_, varMin_, varMax_, shadowThreshold_, shadowValue_); + } +} + +Ptr cv::gpu::createBackgroundSubtractorMOG2(int history, double varThreshold, bool detectShadows) +{ + return makePtr(history, varThreshold, detectShadows); +} + +#endif diff --git a/modules/gpubgsegm/src/precomp.cpp b/modules/gpubgsegm/src/precomp.cpp deleted file mode 100644 index 3c01a2596..000000000 --- a/modules/gpubgsegm/src/precomp.cpp +++ /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 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" diff --git a/modules/gpubgsegm/src/precomp.hpp b/modules/gpubgsegm/src/precomp.hpp index 5f120961b..c61cc08bb 100644 --- a/modules/gpubgsegm/src/precomp.hpp +++ b/modules/gpubgsegm/src/precomp.hpp @@ -46,10 +46,21 @@ #include #include "opencv2/gpubgsegm.hpp" -#include "opencv2/gpuarithm.hpp" -#include "opencv2/gpufilters.hpp" -#include "opencv2/gpuimgproc.hpp" #include "opencv2/core/private.gpu.hpp" +#include "opencv2/opencv_modules.hpp" + +#ifdef HAVE_OPENCV_GPUARITHM +# include "opencv2/gpuarithm.hpp" +#endif + +#ifdef HAVE_OPENCV_GPUFILTERS +# include "opencv2/gpufilters.hpp" +#endif + +#ifdef HAVE_OPENCV_GPUIMGPROC +# include "opencv2/gpuimgproc.hpp" +#endif + #endif /* __OPENCV_PRECOMP_H__ */ diff --git a/modules/gpubgsegm/test/test_bgsegm.cpp b/modules/gpubgsegm/test/test_bgsegm.cpp index a5d187b04..3a287d1bb 100644 --- a/modules/gpubgsegm/test/test_bgsegm.cpp +++ b/modules/gpubgsegm/test/test_bgsegm.cpp @@ -41,7 +41,10 @@ //M*/ #include "test_precomp.hpp" -#include "opencv2/legacy.hpp" + +#ifdef HAVE_OPENCV_LEGACY +# include "opencv2/legacy.hpp" +#endif #ifdef HAVE_CUDA @@ -50,6 +53,7 @@ using namespace cvtest; #if defined(HAVE_XINE) || \ defined(HAVE_GSTREAMER) || \ defined(HAVE_QUICKTIME) || \ + defined(HAVE_QTKIT) || \ defined(HAVE_AVFOUNDATION) || \ defined(HAVE_FFMPEG) || \ defined(WIN32) /* assume that we have ffmpeg */ @@ -62,21 +66,20 @@ using namespace cvtest; ////////////////////////////////////////////////////// // FGDStatModel -#if BUILD_WITH_VIDEO_INPUT_SUPPORT +#if BUILD_WITH_VIDEO_INPUT_SUPPORT && defined(HAVE_OPENCV_LEGACY) namespace cv { - template<> void Ptr::delete_obj() + template<> void DefaultDeleter::operator ()(CvBGStatModel* obj) const { cvReleaseBGStatModel(&obj); } } -PARAM_TEST_CASE(FGDStatModel, cv::gpu::DeviceInfo, std::string, Channels) +PARAM_TEST_CASE(FGDStatModel, cv::gpu::DeviceInfo, std::string) { cv::gpu::DeviceInfo devInfo; std::string inputFile; - int out_cn; virtual void SetUp() { @@ -84,8 +87,6 @@ PARAM_TEST_CASE(FGDStatModel, cv::gpu::DeviceInfo, std::string, Channels) cv::gpu::setDevice(devInfo.deviceID()); inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "video/" + GET_PARAM(1); - - out_cn = GET_PARAM(2); } }; @@ -102,15 +103,10 @@ GPU_TEST_P(FGDStatModel, Update) cv::Ptr model(cvCreateFGDStatModel(&ipl_frame)); cv::gpu::GpuMat d_frame(frame); - cv::gpu::FGDStatModel d_model(out_cn); - d_model.create(d_frame); - - cv::Mat h_background; - cv::Mat h_foreground; - cv::Mat h_background3; - - cv::Mat backgroundDiff; - cv::Mat foregroundDiff; + cv::Ptr d_fgd = cv::gpu::createBackgroundSubtractorFGD(); + cv::gpu::GpuMat d_foreground, d_background; + std::vector< std::vector > foreground_regions; + d_fgd->apply(d_frame, d_foreground); for (int i = 0; i < 5; ++i) { @@ -121,32 +117,23 @@ GPU_TEST_P(FGDStatModel, Update) int gold_count = cvUpdateBGStatModel(&ipl_frame, model); d_frame.upload(frame); - - int count = d_model.update(d_frame); - - ASSERT_EQ(gold_count, count); + d_fgd->apply(d_frame, d_foreground); + d_fgd->getBackgroundImage(d_background); + d_fgd->getForegroundRegions(foreground_regions); + int count = (int) foreground_regions.size(); cv::Mat gold_background = cv::cvarrToMat(model->background); cv::Mat gold_foreground = cv::cvarrToMat(model->foreground); - if (out_cn == 3) - d_model.background.download(h_background3); - else - { - d_model.background.download(h_background); - cv::cvtColor(h_background, h_background3, cv::COLOR_BGRA2BGR); - } - d_model.foreground.download(h_foreground); - - ASSERT_MAT_NEAR(gold_background, h_background3, 1.0); - ASSERT_MAT_NEAR(gold_foreground, h_foreground, 0.0); + ASSERT_MAT_NEAR(gold_background, d_background, 1.0); + ASSERT_MAT_NEAR(gold_foreground, d_foreground, 0.0); + ASSERT_EQ(gold_count, count); } } INSTANTIATE_TEST_CASE_P(GPU_BgSegm, FGDStatModel, testing::Combine( ALL_DEVICES, - testing::Values(std::string("768x576.avi")), - testing::Values(Channels(3), Channels(4)))); + testing::Values(std::string("768x576.avi")))); #endif @@ -193,7 +180,7 @@ GPU_TEST_P(MOG, Update) cap >> frame; ASSERT_FALSE(frame.empty()); - cv::gpu::MOG_GPU mog; + cv::Ptr mog = cv::gpu::createBackgroundSubtractorMOG(); cv::gpu::GpuMat foreground = createMat(frame.size(), CV_8UC1, useRoi); cv::Ptr mog_gold = cv::createBackgroundSubtractorMOG(); @@ -211,7 +198,7 @@ GPU_TEST_P(MOG, Update) cv::swap(temp, frame); } - mog(loadMat(frame, useRoi), foreground, (float)learningRate); + mog->apply(loadMat(frame, useRoi), foreground, learningRate); mog_gold->apply(frame, foreground_gold, learningRate); @@ -267,8 +254,8 @@ GPU_TEST_P(MOG2, Update) cap >> frame; ASSERT_FALSE(frame.empty()); - cv::gpu::MOG2_GPU mog2; - mog2.bShadowDetection = detectShadow; + cv::Ptr mog2 = cv::gpu::createBackgroundSubtractorMOG2(); + mog2->setDetectShadows(detectShadow); cv::gpu::GpuMat foreground = createMat(frame.size(), CV_8UC1, useRoi); cv::Ptr mog2_gold = cv::createBackgroundSubtractorMOG2(); @@ -287,7 +274,7 @@ GPU_TEST_P(MOG2, Update) cv::swap(temp, frame); } - mog2(loadMat(frame, useRoi), foreground); + mog2->apply(loadMat(frame, useRoi), foreground); mog2_gold->apply(frame, foreground_gold); @@ -312,8 +299,8 @@ GPU_TEST_P(MOG2, getBackgroundImage) cv::Mat frame; - cv::gpu::MOG2_GPU mog2; - mog2.bShadowDetection = detectShadow; + cv::Ptr mog2 = cv::gpu::createBackgroundSubtractorMOG2(); + mog2->setDetectShadows(detectShadow); cv::gpu::GpuMat foreground; cv::Ptr mog2_gold = cv::createBackgroundSubtractorMOG2(); @@ -325,13 +312,13 @@ GPU_TEST_P(MOG2, getBackgroundImage) cap >> frame; ASSERT_FALSE(frame.empty()); - mog2(loadMat(frame, useRoi), foreground); + mog2->apply(loadMat(frame, useRoi), foreground); mog2_gold->apply(frame, foreground_gold); } cv::gpu::GpuMat background = createMat(frame.size(), frame.type(), useRoi); - mog2.getBackgroundImage(background); + mog2->getBackgroundImage(background); cv::Mat background_gold; mog2_gold->getBackgroundImage(background_gold); @@ -372,16 +359,15 @@ GPU_TEST_P(GMG, Accuracy) cv::Mat frame = randomMat(size, type, 0, 100); cv::gpu::GpuMat d_frame = loadMat(frame, useRoi); - cv::gpu::GMG_GPU gmg; - gmg.numInitializationFrames = 5; - gmg.smoothingRadius = 0; - gmg.initialize(d_frame.size(), 0, 255); + cv::Ptr gmg = cv::gpu::createBackgroundSubtractorGMG(); + gmg->setNumFrames(5); + gmg->setSmoothingRadius(0); cv::gpu::GpuMat d_fgmask = createMat(size, CV_8UC1, useRoi); - for (int i = 0; i < gmg.numInitializationFrames; ++i) + for (int i = 0; i < gmg->getNumFrames(); ++i) { - gmg(d_frame, d_fgmask); + gmg->apply(d_frame, d_fgmask); // fgmask should be entirely background during training ASSERT_MAT_NEAR(zeros, d_fgmask, 0); @@ -389,7 +375,7 @@ GPU_TEST_P(GMG, Accuracy) frame = randomMat(size, type, 160, 255); d_frame = loadMat(frame, useRoi); - gmg(d_frame, d_fgmask); + gmg->apply(d_frame, d_fgmask); // now fgmask should be entirely foreground ASSERT_MAT_NEAR(fullfg, d_fgmask, 0); diff --git a/modules/gpubgsegm/test/test_precomp.hpp b/modules/gpubgsegm/test/test_precomp.hpp index 0249f5be9..783e9e64c 100644 --- a/modules/gpubgsegm/test/test_precomp.hpp +++ b/modules/gpubgsegm/test/test_precomp.hpp @@ -59,4 +59,7 @@ #include "opencv2/gpubgsegm.hpp" #include "opencv2/video.hpp" +#include "opencv2/opencv_modules.hpp" +#include "cvconfig.h" + #endif diff --git a/modules/gpucodec/CMakeLists.txt b/modules/gpucodec/CMakeLists.txt index b1e0daeaa..7c3be5c0e 100644 --- a/modules/gpucodec/CMakeLists.txt +++ b/modules/gpucodec/CMakeLists.txt @@ -11,7 +11,7 @@ ocv_add_module(gpucodec opencv_highgui) ocv_module_include_directories() ocv_glob_module_sources() -set(extra_libs ${HIGHGUI_LIBRARIES}) +set(extra_libs "") if(HAVE_NVCUVID) list(APPEND extra_libs ${CUDA_CUDA_LIBRARY} ${CUDA_nvcuvid_LIBRARY}) diff --git a/modules/gpucodec/doc/videodec.rst b/modules/gpucodec/doc/videodec.rst index e2da30559..dbf895121 100644 --- a/modules/gpucodec/doc/videodec.rst +++ b/modules/gpucodec/doc/videodec.rst @@ -11,6 +11,9 @@ Video reader interface. .. ocv:class:: gpucodec::VideoReader +.. note:: + + * An example on how to use the videoReader class can be found at opencv_source_code/samples/gpu/video_reader.cpp gpucodec::VideoReader::nextFrame diff --git a/modules/gpucodec/doc/videoenc.rst b/modules/gpucodec/doc/videoenc.rst index 739ec0d70..d4a6814a0 100644 --- a/modules/gpucodec/doc/videoenc.rst +++ b/modules/gpucodec/doc/videoenc.rst @@ -15,6 +15,9 @@ The implementation uses H264 video codec. .. note:: Currently only Windows platform is supported. +.. note:: + + * An example on how to use the videoWriter class can be found at opencv_source_code/samples/gpu/video_writer.cpp gpucodec::VideoWriter::write diff --git a/modules/gpucodec/perf/perf_main.cpp b/modules/gpucodec/perf/perf_main.cpp index 2f4110b87..783965357 100644 --- a/modules/gpucodec/perf/perf_main.cpp +++ b/modules/gpucodec/perf/perf_main.cpp @@ -44,4 +44,4 @@ using namespace perf; -CV_PERF_TEST_MAIN(gpucodec, printCudaInfo()) +CV_PERF_TEST_CUDA_MAIN(gpucodec) diff --git a/modules/gpucodec/perf/perf_precomp.cpp b/modules/gpucodec/perf/perf_precomp.cpp deleted file mode 100644 index 81f16e8f1..000000000 --- a/modules/gpucodec/perf/perf_precomp.cpp +++ /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 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" diff --git a/modules/gpucodec/perf/perf_video.cpp b/modules/gpucodec/perf/perf_video.cpp index f389605d0..c4ab227c8 100644 --- a/modules/gpucodec/perf/perf_video.cpp +++ b/modules/gpucodec/perf/perf_video.cpp @@ -50,6 +50,7 @@ using namespace perf; #if defined(HAVE_XINE) || \ defined(HAVE_GSTREAMER) || \ defined(HAVE_QUICKTIME) || \ + defined(HAVE_QTKIT) || \ defined(HAVE_AVFOUNDATION) || \ defined(HAVE_FFMPEG) || \ defined(WIN32) /* assume that we have ffmpeg */ diff --git a/modules/gpucodec/src/ffmpeg_video_source.cpp b/modules/gpucodec/src/ffmpeg_video_source.cpp index b5a73875b..86d1b5931 100644 --- a/modules/gpucodec/src/ffmpeg_video_source.cpp +++ b/modules/gpucodec/src/ffmpeg_video_source.cpp @@ -45,10 +45,6 @@ #ifdef HAVE_NVCUVID -#if defined(HAVE_FFMPEG) && defined(BUILD_SHARED_LIBS) && !defined(WIN32) - #include "../src/cap_ffmpeg_impl.hpp" -#endif - using namespace cv; using namespace cv::gpucodec; using namespace cv::gpucodec::detail; diff --git a/modules/gpucodec/src/precomp.cpp b/modules/gpucodec/src/precomp.cpp deleted file mode 100644 index 3c01a2596..000000000 --- a/modules/gpucodec/src/precomp.cpp +++ /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 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" diff --git a/modules/gpucodec/src/thread.cpp b/modules/gpucodec/src/thread.cpp index b936d8e21..6784a1c8e 100644 --- a/modules/gpucodec/src/thread.cpp +++ b/modules/gpucodec/src/thread.cpp @@ -167,9 +167,4 @@ void cv::gpucodec::detail::Thread::sleep(int ms) #endif } -template <> void cv::Ptr::delete_obj() -{ - if (obj) delete obj; -} - #endif // HAVE_NVCUVID diff --git a/modules/gpucodec/src/thread.hpp b/modules/gpucodec/src/thread.hpp index ccda5b5c7..c69367f96 100644 --- a/modules/gpucodec/src/thread.hpp +++ b/modules/gpucodec/src/thread.hpp @@ -67,8 +67,4 @@ private: }}} -namespace cv { - template <> void Ptr::delete_obj(); -} - #endif // __THREAD_WRAPPERS_HPP__ diff --git a/modules/gpucodec/src/video_reader.cpp b/modules/gpucodec/src/video_reader.cpp index 67e9cd107..3e758087a 100644 --- a/modules/gpucodec/src/video_reader.cpp +++ b/modules/gpucodec/src/video_reader.cpp @@ -58,12 +58,14 @@ namespace cv { namespace gpu { namespace cudev void NV12_to_RGB(const PtrStepb decodedFrame, PtrStepSz interopFrame, cudaStream_t stream = 0); }}} +using namespace cv::gpucodec::detail; + namespace { class VideoReaderImpl : public VideoReader { public: - explicit VideoReaderImpl(const Ptr& source); + explicit VideoReaderImpl(const Ptr& source); ~VideoReaderImpl(); bool nextFrame(OutputArray frame); @@ -71,11 +73,11 @@ namespace FormatInfo format() const; private: - Ptr videoSource_; + Ptr videoSource_; - Ptr frameQueue_; - Ptr videoDecoder_; - Ptr videoParser_; + Ptr frameQueue_; + Ptr videoDecoder_; + Ptr videoParser_; CUvideoctxlock lock_; @@ -87,7 +89,7 @@ namespace return videoSource_->format(); } - VideoReaderImpl::VideoReaderImpl(const Ptr& source) : + VideoReaderImpl::VideoReaderImpl(const Ptr& source) : videoSource_(source), lock_(0) { @@ -99,9 +101,9 @@ namespace cuSafeCall( cuCtxGetCurrent(&ctx) ); cuSafeCall( cuvidCtxLockCreate(&lock_, ctx) ); - frameQueue_ = new detail::FrameQueue; - videoDecoder_ = new detail::VideoDecoder(videoSource_->format(), lock_); - videoParser_ = new detail::VideoParser(videoDecoder_, frameQueue_); + frameQueue_.reset(new FrameQueue); + videoDecoder_.reset(new VideoDecoder(videoSource_->format(), lock_)); + videoParser_.reset(new VideoParser(videoDecoder_, frameQueue_)); videoSource_->setVideoParser(videoParser_); videoSource_->start(); @@ -159,7 +161,7 @@ namespace return false; // Wait a bit - detail::Thread::sleep(1); + Thread::sleep(1); } bool isProgressive = displayInfo.progressive_frame != 0; @@ -212,25 +214,25 @@ Ptr cv::gpucodec::createVideoReader(const String& filename) { CV_Assert( !filename.empty() ); - Ptr videoSource; + Ptr videoSource; try { - videoSource = new detail::CuvidVideoSource(filename); + videoSource.reset(new CuvidVideoSource(filename)); } catch (...) { - Ptr source(new detail::FFmpegVideoSource(filename)); - videoSource = new detail::RawVideoSourceWrapper(source); + Ptr source(new FFmpegVideoSource(filename)); + videoSource.reset(new RawVideoSourceWrapper(source)); } - return new VideoReaderImpl(videoSource); + return makePtr(videoSource); } Ptr cv::gpucodec::createVideoReader(const Ptr& source) { - Ptr videoSource(new detail::RawVideoSourceWrapper(source)); - return new VideoReaderImpl(videoSource); + Ptr videoSource(new RawVideoSourceWrapper(source)); + return makePtr(videoSource); } #endif // HAVE_NVCUVID diff --git a/modules/gpucodec/src/video_source.cpp b/modules/gpucodec/src/video_source.cpp index ce6a1bd8c..e4241cf2d 100644 --- a/modules/gpucodec/src/video_source.cpp +++ b/modules/gpucodec/src/video_source.cpp @@ -69,7 +69,7 @@ void cv::gpucodec::detail::RawVideoSourceWrapper::start() { stop_ = false; hasError_ = false; - thread_ = new Thread(readLoop, this); + thread_.reset(new Thread(readLoop, this)); } void cv::gpucodec::detail::RawVideoSourceWrapper::stop() diff --git a/modules/gpucodec/src/video_writer.cpp b/modules/gpucodec/src/video_writer.cpp index 6ffb7c12d..a1484c2b2 100644 --- a/modules/gpucodec/src/video_writer.cpp +++ b/modules/gpucodec/src/video_writer.cpp @@ -908,12 +908,12 @@ Ptr cv::gpucodec::createVideoWriter(const String& fileName, Size fr Ptr cv::gpucodec::createVideoWriter(const Ptr& encoderCallback, Size frameSize, double fps, SurfaceFormat format) { - return new VideoWriterImpl(encoderCallback, frameSize, fps, format); + return makePtr(encoderCallback, frameSize, fps, format); } Ptr cv::gpucodec::createVideoWriter(const Ptr& encoderCallback, Size frameSize, double fps, const EncoderParams& params, SurfaceFormat format) { - return new VideoWriterImpl(encoderCallback, frameSize, fps, params, format); + return makePtr(encoderCallback, frameSize, fps, params, format); } #endif // !defined HAVE_CUDA || !defined WIN32 diff --git a/modules/gpucodec/test/test_precomp.cpp b/modules/gpucodec/test/test_precomp.cpp deleted file mode 100644 index 0fb652180..000000000 --- a/modules/gpucodec/test/test_precomp.cpp +++ /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 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" diff --git a/modules/gpucodec/test/test_precomp.hpp b/modules/gpucodec/test/test_precomp.hpp index 0dc79935d..95e70d46d 100644 --- a/modules/gpucodec/test/test_precomp.hpp +++ b/modules/gpucodec/test/test_precomp.hpp @@ -57,4 +57,6 @@ #include "opencv2/gpucodec.hpp" #include "opencv2/highgui.hpp" +#include "cvconfig.h" + #endif diff --git a/modules/gpufeatures2d/perf/perf_features2d.cpp b/modules/gpufeatures2d/perf/perf_features2d.cpp index 9396ba290..fd2852633 100644 --- a/modules/gpufeatures2d/perf/perf_features2d.cpp +++ b/modules/gpufeatures2d/perf/perf_features2d.cpp @@ -123,7 +123,7 @@ PERF_TEST_P(Image_NFeatures, ORB, sortKeyPoints(gpu_keypoints, gpu_descriptors); - SANITY_CHECK_KEYPOINTS(gpu_keypoints); + SANITY_CHECK_KEYPOINTS(gpu_keypoints, 1e-4); SANITY_CHECK(gpu_descriptors); } else diff --git a/modules/gpufeatures2d/perf/perf_main.cpp b/modules/gpufeatures2d/perf/perf_main.cpp index 0fd79fde3..5e7fb1b8b 100644 --- a/modules/gpufeatures2d/perf/perf_main.cpp +++ b/modules/gpufeatures2d/perf/perf_main.cpp @@ -44,4 +44,4 @@ using namespace perf; -CV_PERF_TEST_MAIN(gpufeatures2d, printCudaInfo()) +CV_PERF_TEST_CUDA_MAIN(gpufeatures2d) diff --git a/modules/gpufeatures2d/perf/perf_precomp.cpp b/modules/gpufeatures2d/perf/perf_precomp.cpp deleted file mode 100644 index 81f16e8f1..000000000 --- a/modules/gpufeatures2d/perf/perf_precomp.cpp +++ /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 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" diff --git a/modules/gpufeatures2d/src/cuda/orb.cu b/modules/gpufeatures2d/src/cuda/orb.cu index 1e8864801..571ca12bd 100644 --- a/modules/gpufeatures2d/src/cuda/orb.cu +++ b/modules/gpufeatures2d/src/cuda/orb.cu @@ -197,8 +197,8 @@ namespace cv { namespace gpu { namespace cudev if (threadIdx.x == 0) { float kp_dir = ::atan2f((float)m_01, (float)m_10); - kp_dir += (kp_dir < 0) * (2.0f * CV_PI); - kp_dir *= 180.0f / CV_PI; + kp_dir += (kp_dir < 0) * (2.0f * CV_PI_F); + kp_dir *= 180.0f / CV_PI_F; angle[ptidx] = kp_dir; } @@ -349,7 +349,7 @@ namespace cv { namespace gpu { namespace cudev if (ptidx < npoints && descidx < dsize) { float angle = angle_[ptidx]; - angle *= (float)(CV_PI / 180.f); + angle *= (float)(CV_PI_F / 180.f); float sina, cosa; ::sincosf(angle, &sina, &cosa); diff --git a/modules/gpufeatures2d/src/precomp.cpp b/modules/gpufeatures2d/src/precomp.cpp deleted file mode 100644 index 3c01a2596..000000000 --- a/modules/gpufeatures2d/src/precomp.cpp +++ /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 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" diff --git a/modules/gpufeatures2d/test/test_precomp.cpp b/modules/gpufeatures2d/test/test_precomp.cpp deleted file mode 100644 index 0fb652180..000000000 --- a/modules/gpufeatures2d/test/test_precomp.cpp +++ /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 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" diff --git a/modules/gpufeatures2d/test/test_precomp.hpp b/modules/gpufeatures2d/test/test_precomp.hpp index 7725d3f3d..4ce8f7849 100644 --- a/modules/gpufeatures2d/test/test_precomp.hpp +++ b/modules/gpufeatures2d/test/test_precomp.hpp @@ -57,4 +57,6 @@ #include "opencv2/gpufeatures2d.hpp" #include "opencv2/features2d.hpp" +#include "cvconfig.h" + #endif diff --git a/modules/gpufilters/doc/filtering.rst b/modules/gpufilters/doc/filtering.rst index 925b05f2c..cb824bf2a 100644 --- a/modules/gpufilters/doc/filtering.rst +++ b/modules/gpufilters/doc/filtering.rst @@ -5,7 +5,9 @@ Image Filtering Functions and classes described in this section are used to perform various linear or non-linear filtering operations on 2D images. +.. note:: + * An example containing all basic morphology operators like erode and dilate can be found at opencv_source_code/samples/gpu/morphology.cpp gpu::Filter ----------- diff --git a/modules/gpufilters/perf/perf_main.cpp b/modules/gpufilters/perf/perf_main.cpp index b5a3eda40..44b3129e1 100644 --- a/modules/gpufilters/perf/perf_main.cpp +++ b/modules/gpufilters/perf/perf_main.cpp @@ -44,4 +44,4 @@ using namespace perf; -CV_PERF_TEST_MAIN(gpufilters, printCudaInfo()) +CV_PERF_TEST_CUDA_MAIN(gpufilters) diff --git a/modules/gpufilters/perf/perf_precomp.cpp b/modules/gpufilters/perf/perf_precomp.cpp deleted file mode 100644 index 81f16e8f1..000000000 --- a/modules/gpufilters/perf/perf_precomp.cpp +++ /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 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" diff --git a/modules/gpufilters/src/filtering.cpp b/modules/gpufilters/src/filtering.cpp index 7f02bdac5..0043174cb 100644 --- a/modules/gpufilters/src/filtering.cpp +++ b/modules/gpufilters/src/filtering.cpp @@ -169,7 +169,7 @@ Ptr cv::gpu::createBoxFilter(int srcType, int dstType, Size ksize, Point dstType = CV_MAKE_TYPE(CV_MAT_DEPTH(dstType), CV_MAT_CN(srcType)); - return new NPPBoxFilter(srcType, dstType, ksize, anchor, borderMode, borderVal); + return makePtr(srcType, dstType, ksize, anchor, borderMode, borderVal); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -230,22 +230,22 @@ namespace switch (srcType) { case CV_8UC1: - func_ = cudev::filter2D; + func_ = cv::gpu::cudev::filter2D; break; case CV_8UC4: - func_ = cudev::filter2D; + func_ = cv::gpu::cudev::filter2D; break; case CV_16UC1: - func_ = cudev::filter2D; + func_ = cv::gpu::cudev::filter2D; break; case CV_16UC4: - func_ = cudev::filter2D; + func_ = cv::gpu::cudev::filter2D; break; case CV_32FC1: - func_ = cudev::filter2D; + func_ = cv::gpu::cudev::filter2D; break; case CV_32FC4: - func_ = cudev::filter2D; + func_ = cv::gpu::cudev::filter2D; break; } } @@ -277,7 +277,7 @@ Ptr cv::gpu::createLinearFilter(int srcType, int dstType, InputArray ker dstType = CV_MAKE_TYPE(CV_MAT_DEPTH(dstType), CV_MAT_CN(srcType)); - return new LinearFilter(srcType, dstType, kernel, anchor, borderMode, borderVal); + return makePtr(srcType, dstType, kernel, anchor, borderMode, borderVal); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -409,7 +409,7 @@ namespace ensureSizeIsEnough(src.size(), bufType_, buf_); DeviceInfo devInfo; - const int cc = devInfo.major() * 10 + devInfo.minor(); + const int cc = devInfo.majorVersion() * 10 + devInfo.minorVersion(); cudaStream_t stream = StreamAccessor::getStream(_stream); @@ -428,7 +428,7 @@ Ptr cv::gpu::createSeparableLinearFilter(int srcType, int dstType, Input if (columnBorderMode < 0) columnBorderMode = rowBorderMode; - return new SeparableLinearFilter(srcType, dstType, rowKernel, columnKernel, anchor, rowBorderMode, columnBorderMode); + return makePtr(srcType, dstType, rowKernel, columnKernel, anchor, rowBorderMode, columnBorderMode); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -748,27 +748,27 @@ Ptr cv::gpu::createMorphologyFilter(int op, int srcType, InputArray kern { case MORPH_ERODE: case MORPH_DILATE: - return new MorphologyFilter(op, srcType, kernel, anchor, iterations); + return makePtr(op, srcType, kernel, anchor, iterations); break; case MORPH_OPEN: - return new MorphologyOpenFilter(srcType, kernel, anchor, iterations); + return makePtr(srcType, kernel, anchor, iterations); break; case MORPH_CLOSE: - return new MorphologyCloseFilter(srcType, kernel, anchor, iterations); + return makePtr(srcType, kernel, anchor, iterations); break; case MORPH_GRADIENT: - return new MorphologyGradientFilter(srcType, kernel, anchor, iterations); + return makePtr(srcType, kernel, anchor, iterations); break; case MORPH_TOPHAT: - return new MorphologyTophatFilter(srcType, kernel, anchor, iterations); + return makePtr(srcType, kernel, anchor, iterations); break; case MORPH_BLACKHAT: - return new MorphologyBlackhatFilter(srcType, kernel, anchor, iterations); + return makePtr(srcType, kernel, anchor, iterations); break; default: @@ -782,7 +782,7 @@ Ptr cv::gpu::createMorphologyFilter(int op, int srcType, InputArray kern namespace { - enum + enum RankType { RANK_MAX, RANK_MIN @@ -862,12 +862,12 @@ namespace Ptr cv::gpu::createBoxMaxFilter(int srcType, Size ksize, Point anchor, int borderMode, Scalar borderVal) { - return new NPPRankFilter(RANK_MAX, srcType, ksize, anchor, borderMode, borderVal); + return makePtr(RANK_MAX, srcType, ksize, anchor, borderMode, borderVal); } Ptr cv::gpu::createBoxMinFilter(int srcType, Size ksize, Point anchor, int borderMode, Scalar borderVal) { - return new NPPRankFilter(RANK_MIN, srcType, ksize, anchor, borderMode, borderVal); + return makePtr(RANK_MIN, srcType, ksize, anchor, borderMode, borderVal); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -931,7 +931,7 @@ namespace Ptr cv::gpu::createRowSumFilter(int srcType, int dstType, int ksize, int anchor, int borderMode, Scalar borderVal) { - return new NppRowSumFilter(srcType, dstType, ksize, anchor, borderMode, borderVal); + return makePtr(srcType, dstType, ksize, anchor, borderMode, borderVal); } namespace @@ -992,7 +992,7 @@ namespace Ptr cv::gpu::createColumnSumFilter(int srcType, int dstType, int ksize, int anchor, int borderMode, Scalar borderVal) { - return new NppColumnSumFilter(srcType, dstType, ksize, anchor, borderMode, borderVal); + return makePtr(srcType, dstType, ksize, anchor, borderMode, borderVal); } #endif diff --git a/modules/gpufilters/src/precomp.cpp b/modules/gpufilters/src/precomp.cpp deleted file mode 100644 index 3c01a2596..000000000 --- a/modules/gpufilters/src/precomp.cpp +++ /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 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" diff --git a/modules/gpufilters/test/test_precomp.cpp b/modules/gpufilters/test/test_precomp.cpp deleted file mode 100644 index 0fb652180..000000000 --- a/modules/gpufilters/test/test_precomp.cpp +++ /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 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" diff --git a/modules/gpufilters/test/test_precomp.hpp b/modules/gpufilters/test/test_precomp.hpp index 95984929f..7dfe713d3 100644 --- a/modules/gpufilters/test/test_precomp.hpp +++ b/modules/gpufilters/test/test_precomp.hpp @@ -57,4 +57,6 @@ #include "opencv2/gpufilters.hpp" #include "opencv2/imgproc.hpp" +#include "cvconfig.h" + #endif diff --git a/modules/gpuimgproc/CMakeLists.txt b/modules/gpuimgproc/CMakeLists.txt index 3b9bd0725..dfecf1d21 100644 --- a/modules/gpuimgproc/CMakeLists.txt +++ b/modules/gpuimgproc/CMakeLists.txt @@ -6,4 +6,4 @@ set(the_description "GPU-accelerated Image Processing") ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127 /wd4100 /wd4324 /wd4512 /wd4515 -Wundef -Wmissing-declarations -Wshadow -Wunused-parameter) -ocv_define_module(gpuimgproc opencv_imgproc opencv_gpufilters OPTIONAL opencv_gpuarithm) +ocv_define_module(gpuimgproc opencv_imgproc OPTIONAL opencv_gpuarithm opencv_gpufilters) diff --git a/modules/gpuimgproc/doc/color.rst b/modules/gpuimgproc/doc/color.rst index 70de236ea..b1e8e03be 100644 --- a/modules/gpuimgproc/doc/color.rst +++ b/modules/gpuimgproc/doc/color.rst @@ -6,16 +6,16 @@ Color space processing 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()) +.. ocv:function:: void gpu::cvtColor(InputArray src, OutputArray 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 dst: Destination image. - :param code: Color space conversion code. For details, see :ocv:func:`cvtColor` . Conversion to/from Luv and Bayer color spaces is not supported. + :param code: Color space conversion code. For details, see :ocv:func:`cvtColor` . :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`` . @@ -27,11 +27,45 @@ Converts an image from one color space to another. +gpu::demosaicing +---------------- +Converts an image from Bayer pattern to RGB or grayscale. + +.. ocv:function:: void gpu::demosaicing(InputArray src, OutputArray dst, int code, int dcn = -1, Stream& stream = Stream::Null()) + + :param src: Source image (8-bit or 16-bit single channel). + + :param dst: Destination image. + + :param code: Color space conversion code (see the description below). + + :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. + +The function can do the following transformations: + +* Demosaicing using bilinear interpolation + + * ``COLOR_BayerBG2GRAY`` , ``COLOR_BayerGB2GRAY`` , ``COLOR_BayerRG2GRAY`` , ``COLOR_BayerGR2GRAY`` + + * ``COLOR_BayerBG2BGR`` , ``COLOR_BayerGB2BGR`` , ``COLOR_BayerRG2BGR`` , ``COLOR_BayerGR2BGR`` + +* Demosaicing using Malvar-He-Cutler algorithm ([MHT2011]_) + + * ``COLOR_BayerBG2GRAY_MHT`` , ``COLOR_BayerGB2GRAY_MHT`` , ``COLOR_BayerRG2GRAY_MHT`` , ``COLOR_BayerGR2GRAY_MHT`` + + * ``COLOR_BayerBG2BGR_MHT`` , ``COLOR_BayerGB2BGR_MHT`` , ``COLOR_BayerRG2BGR_MHT`` , ``COLOR_BayerGR2BGR_MHT`` + +.. 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()) +.. ocv:function:: void gpu::swapChannels(InputOutputArray image, const int dstOrder[4], Stream& stream = Stream::Null()) :param image: Source image. Supports only ``CV_8UC4`` type. @@ -43,11 +77,27 @@ The methods support arbitrary permutations of the original channels, including r +gpu::gammaCorrection +-------------------- +Routines for correcting image color gamma. + +.. ocv:function:: void gpu::gammaCorrection(InputArray src, OutputArray dst, bool forward = true, Stream& stream = Stream::Null()) + + :param src: Source image (3- or 4-channel 8 bit). + + :param dst: Destination image. + + :param forward: ``true`` for forward gamma correction or ``false`` for inverse gamma correction. + + :param stream: Stream for the asynchronous version. + + + 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()) +.. ocv:function:: void gpu::alphaComp(InputArray img1, InputArray img2, OutputArray dst, int alpha_op, Stream& stream = Stream::Null()) :param img1: First image. Supports ``CV_8UC4`` , ``CV_16UC4`` , ``CV_32SC4`` and ``CV_32FC4`` types. @@ -72,3 +122,10 @@ Composites two images using alpha opacity values contained in each image. * **ALPHA_PREMUL** :param stream: Stream for the asynchronous version. + +.. note:: + + * An example demonstrating the use of alphaComp can be found at opencv_source_code/samples/gpu/alpha_comp.cpp + + +.. [MHT2011] Pascal Getreuer, Malvar-He-Cutler Linear Image Demosaicking, Image Processing On Line, 2011 diff --git a/modules/gpuimgproc/doc/feature_detection.rst b/modules/gpuimgproc/doc/feature_detection.rst index c38b8c200..fc5e592cf 100644 --- a/modules/gpuimgproc/doc/feature_detection.rst +++ b/modules/gpuimgproc/doc/feature_detection.rst @@ -5,15 +5,41 @@ Feature Detection -gpu::cornerHarris ---------------------- -Computes the Harris cornerness criteria at each image pixel. +gpu::CornernessCriteria +----------------------- +.. ocv:class:: gpu::CornernessCriteria : public Algorithm -.. ocv:function:: void gpu::cornerHarris(const GpuMat& src, GpuMat& dst, int blockSize, int ksize, double k, int borderType=BORDER_REFLECT101) +Base class for Cornerness Criteria computation. :: - :param src: Source image. Only ``CV_8UC1`` and ``CV_32FC1`` images are supported for now. + class CV_EXPORTS CornernessCriteria : public Algorithm + { + public: + virtual void compute(InputArray src, OutputArray dst, Stream& stream = Stream::Null()) = 0; + }; - :param dst: Destination image containing cornerness values. It has the same size as ``src`` and ``CV_32FC1`` type. + + +gpu::CornernessCriteria::compute +-------------------------------- +Computes the cornerness criteria at each image pixel. + +.. ocv:function:: void gpu::CornernessCriteria::compute(InputArray src, OutputArray dst, Stream& stream = Stream::Null()) + + :param src: Source image. + + :param dst: Destination image containing cornerness values. It will have the same size as ``src`` and ``CV_32FC1`` type. + + :param stream: Stream for the asynchronous version. + + + +gpu::createHarrisCorner +----------------------- +Creates implementation for Harris cornerness criteria. + +.. ocv:function:: Ptr gpu::createHarrisCorner(int srcType, int blockSize, int ksize, double k, int borderType = BORDER_REFLECT101) + + :param srcType: Input source type. Only ``CV_8UC1`` and ``CV_32FC1`` are supported for now. :param blockSize: Neighborhood size. @@ -27,55 +53,70 @@ Computes the Harris cornerness criteria at each image pixel. -gpu::cornerMinEigenVal --------------------------- -Computes the minimum eigen value of a 2x2 derivative covariation matrix at each pixel (the cornerness criteria). +gpu::createMinEigenValCorner +---------------------------- +Creates implementation for the minimum eigen value of a 2x2 derivative covariation matrix (the cornerness criteria). -.. ocv:function:: void gpu::cornerMinEigenVal(const GpuMat& src, GpuMat& dst, int blockSize, int ksize, int borderType=BORDER_REFLECT101) +.. ocv:function:: Ptr gpu::createMinEigenValCorner(int srcType, 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 srcType: Input source type. Only ``CV_8UC1`` and ``CV_32FC1`` are supported for now. :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. + :param borderType: Pixel extrapolation method. Only ``BORDER_REFLECT101`` and ``BORDER_REPLICATE`` are supported for now. .. seealso:: :ocv:func:`cornerMinEigenVal` -gpu::GoodFeaturesToTrackDetector_GPU ------------------------------------- -.. ocv:class:: gpu::GoodFeaturesToTrackDetector_GPU +gpu::CornersDetector +-------------------- +.. ocv:class:: gpu::CornersDetector : public Algorithm -Class used for strong corners detection on an image. :: +Base class for Corners Detector. :: - class GoodFeaturesToTrackDetector_GPU + class CV_EXPORTS CornersDetector : public Algorithm { 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(); + virtual void detect(InputArray image, OutputArray corners, InputArray mask = noArray()) = 0; }; -The class finds the most prominent corners in the image. + + +gpu::CornersDetector::detect +---------------------------- +Determines strong corners on an image. + +.. ocv:function:: void gpu::CornersDetector::detect(InputArray image, OutputArray corners, InputArray mask = noArray()) + + :param image: Input 8-bit or floating-point 32-bit, single-channel image. + + :param corners: Output vector of detected corners (1-row matrix with CV_32FC2 type with corners positions). + + :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. + + + +gpu::createGoodFeaturesToTrackDetector +-------------------------------------- +Creates implementation for :ocv:class:`gpu::CornersDetector` . + +.. ocv:function:: Ptr gpu::createGoodFeaturesToTrackDetector(int srcType, int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 0.0, int blockSize = 3, bool useHarrisDetector = false, double harrisK = 0.04) + + :param srcType: Input source type. Only ``CV_8UC1`` and ``CV_32FC1`` are supported for now. + + :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:`cornerMinEigenVal` ) or the Harris function response (see :ocv:func:`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:`cornerHarris`) or :ocv:func:`cornerMinEigenVal`. + + :param harrisK: Free parameter of the Harris detector. .. seealso:: :ocv:func:`goodFeaturesToTrack` diff --git a/modules/gpuimgproc/doc/histogram.rst b/modules/gpuimgproc/doc/histogram.rst index 7b29de6ba..dfdf32286 100644 --- a/modules/gpuimgproc/doc/histogram.rst +++ b/modules/gpuimgproc/doc/histogram.rst @@ -5,11 +5,89 @@ Histogram Calculation +gpu::calcHist +------------- +Calculates histogram for one channel 8-bit image. + +.. ocv:function:: void gpu::calcHist(InputArray src, OutputArray hist, Stream& stream = Stream::Null()) + + :param src: Source image with ``CV_8UC1`` type. + + :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(InputArray src, OutputArray dst, Stream& stream = Stream::Null()) + +.. ocv:function:: void gpu::equalizeHist(InputArray src, OutputArray dst, InputOutputArray buf, Stream& stream = Stream::Null()) + + :param src: Source image with ``CV_8UC1`` type. + + :param dst: Destination image. + + :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::CLAHE +---------- +.. ocv:class:: gpu::CLAHE : public cv::CLAHE + +Base class for Contrast Limited Adaptive Histogram Equalization. :: + + class CV_EXPORTS CLAHE : public cv::CLAHE + { + public: + using cv::CLAHE::apply; + virtual void apply(InputArray src, OutputArray dst, Stream& stream) = 0; + }; + + + +gpu::CLAHE::apply +----------------- +Equalizes the histogram of a grayscale image using Contrast Limited Adaptive Histogram Equalization. + +.. ocv:function:: void gpu::CLAHE::apply(InputArray src, OutputArray dst) + +.. ocv:function:: void gpu::CLAHE::apply(InputArray src, OutputArray dst, Stream& stream) + + :param src: Source image with ``CV_8UC1`` type. + + :param dst: Destination image. + + :param stream: Stream for the asynchronous version. + + + +gpu::createCLAHE +---------------- +Creates implementation for :ocv:class:`gpu::CLAHE` . + +.. ocv:function:: Ptr createCLAHE(double clipLimit = 40.0, Size tileGridSize = Size(8, 8)) + + :param clipLimit: Threshold for contrast limiting. + + :param tileGridSize: Size of grid for histogram equalization. Input image will be divided into equally sized rectangular tiles. ``tileGridSize`` defines the number of tiles in row and column. + + + + gpu::evenLevels -------------------- +--------------- Computes levels with even distribution. -.. ocv:function:: void gpu::evenLevels(GpuMat& levels, int nLevels, int lowerLevel, int upperLevel) +.. ocv:function:: void gpu::evenLevels(OutputArray levels, int nLevels, int lowerLevel, int upperLevel) :param levels: Destination array. ``levels`` has 1 row, ``nLevels`` columns, and the ``CV_32SC1`` type. @@ -22,16 +100,16 @@ Computes levels with even distribution. 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(InputArray src, OutputArray 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(InputArray src, OutputArray hist, InputOutputArray 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(InputArray 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() ) +.. ocv:function:: void gpu::histEven(InputArray src, GpuMat hist[4], InputOutputArray 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. @@ -50,12 +128,16 @@ Calculates a histogram with evenly distributed bins. 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(InputArray src, OutputArray hist, InputArray levels, Stream& stream = Stream::Null()) -.. ocv:function:: void gpu::histRange(const GpuMat& src, GpuMat& hist, const GpuMat& levels, GpuMat& buf, Stream& stream = Stream::Null()) +.. ocv:function:: void gpu::histRange(InputArray src, OutputArray hist, InputArray levels, InputOutputArray buf, Stream& stream = Stream::Null()) + +.. ocv:function:: void gpu::histRange(InputArray src, GpuMat hist[4], const GpuMat levels[4], Stream& stream = Stream::Null()) + +.. ocv:function:: void gpu::histRange(InputArray src, GpuMat hist[4], const GpuMat levels[4], InputOutputArray 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. @@ -66,39 +148,3 @@ Calculates a histogram with bins determined by the ``levels`` array. :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` diff --git a/modules/gpuimgproc/doc/hough.rst b/modules/gpuimgproc/doc/hough.rst index 33afabbb6..ec7117198 100644 --- a/modules/gpuimgproc/doc/hough.rst +++ b/modules/gpuimgproc/doc/hough.rst @@ -5,18 +5,70 @@ Hough Transform -gpu::HoughLines ---------------- +gpu::HoughLinesDetector +----------------------- +.. ocv:class:: gpu::HoughLinesDetector : public Algorithm + +Base class for lines detector algorithm. :: + + class CV_EXPORTS HoughLinesDetector : public Algorithm + { + public: + virtual void detect(InputArray src, OutputArray lines) = 0; + virtual void downloadResults(InputArray d_lines, OutputArray h_lines, OutputArray h_votes = noArray()) = 0; + + virtual void setRho(float rho) = 0; + virtual float getRho() const = 0; + + virtual void setTheta(float theta) = 0; + virtual float getTheta() const = 0; + + virtual void setThreshold(int threshold) = 0; + virtual int getThreshold() const = 0; + + virtual void setDoSort(bool doSort) = 0; + virtual bool getDoSort() const = 0; + + virtual void setMaxLines(int maxLines) = 0; + virtual int getMaxLines() const = 0; + }; + + + +gpu::HoughLinesDetector::detect +------------------------------- 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) +.. ocv:function:: void gpu::HoughLinesDetector::detect(InputArray src, OutputArray lines) :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}` ). +.. seealso:: :ocv:func:`HoughLines` + + + +gpu::HoughLinesDetector::downloadResults +---------------------------------------- +Downloads results from :ocv:func:`gpu::HoughLinesDetector::detect` to host memory. + +.. ocv:function:: void gpu::HoughLinesDetector::downloadResults(InputArray d_lines, OutputArray h_lines, OutputArray h_votes = noArray()) + + :param d_lines: Result of :ocv:func:`gpu::HoughLinesDetector::detect` . + + :param h_lines: Output host array. + + :param h_votes: Optional output array for line's votes. + + + +gpu::createHoughLinesDetector +----------------------------- +Creates implementation for :ocv:class:`gpu::HoughLinesDetector` . + +.. ocv:function:: Ptr gpu::createHoughLinesDetector(float rho, float theta, int threshold, bool doSort = false, int maxLines = 4096) + :param rho: Distance resolution of the accumulator in pixels. :param theta: Angle resolution of the accumulator in radians. @@ -27,47 +79,132 @@ Finds lines in a binary image using the classical Hough transform. :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::HoughSegmentDetector +------------------------- +.. ocv:class:: gpu::HoughSegmentDetector : public Algorithm + +Base class for line segments detector algorithm. :: + + class CV_EXPORTS HoughSegmentDetector : public Algorithm + { + public: + virtual void detect(InputArray src, OutputArray lines) = 0; + + virtual void setRho(float rho) = 0; + virtual float getRho() const = 0; + + virtual void setTheta(float theta) = 0; + virtual float getTheta() const = 0; + + virtual void setMinLineLength(int minLineLength) = 0; + virtual int getMinLineLength() const = 0; + + virtual void setMaxLineGap(int maxLineGap) = 0; + virtual int getMaxLineGap() const = 0; + + virtual void setMaxLines(int maxLines) = 0; + virtual int getMaxLines() const = 0; + }; + +.. note:: + + * An example using the Hough segment detector can be found at opencv_source_code/samples/gpu/houghlines.cpp + + +gpu::HoughSegmentDetector::detect +--------------------------------- +Finds line segments in a binary image using the probabilistic Hough transform. + +.. ocv:function:: void gpu::HoughSegmentDetector::detect(InputArray src, OutputArray lines) + + :param src: 8-bit, single-channel binary source image. + + :param lines: Output vector of lines. Each line is represented by a 4-element vector :math:`(x_1, y_1, x_2, y_2)` , where :math:`(x_1,y_1)` and :math:`(x_2, y_2)` are the ending points of each detected line segment. + +.. seealso:: :ocv:func:`HoughLinesP` -gpu::HoughLinesDownload ------------------------ -Downloads results from :ocv:func:`gpu::HoughLines` to host memory. +gpu::createHoughSegmentDetector +------------------------------- +Creates implementation for :ocv:class:`gpu::HoughSegmentDetector` . -.. ocv:function:: void gpu::HoughLinesDownload(const GpuMat& d_lines, OutputArray h_lines, OutputArray h_votes = noArray()) +.. ocv:function:: Ptr gpu::createHoughSegmentDetector(float rho, float theta, int minLineLength, int maxLineGap, int maxLines = 4096) - :param d_lines: Result of :ocv:func:`gpu::HoughLines` . + :param rho: Distance resolution of the accumulator in pixels. - :param h_lines: Output host array. + :param theta: Angle resolution of the accumulator in radians. - :param h_votes: Optional output array for line's votes. + :param minLineLength: Minimum line length. Line segments shorter than that are rejected. -.. seealso:: :ocv:func:`gpu::HoughLines` + :param maxLineGap: Maximum allowed gap between points on the same line to link them. + + :param maxLines: Maximum number of output lines. -gpu::HoughCircles ------------------ +gpu::HoughCirclesDetector +------------------------- +.. ocv:class:: gpu::HoughCirclesDetector : public Algorithm + +Base class for circles detector algorithm. :: + + class CV_EXPORTS HoughCirclesDetector : public Algorithm + { + public: + virtual void detect(InputArray src, OutputArray circles) = 0; + + virtual void setDp(float dp) = 0; + virtual float getDp() const = 0; + + virtual void setMinDist(float minDist) = 0; + virtual float getMinDist() const = 0; + + virtual void setCannyThreshold(int cannyThreshold) = 0; + virtual int getCannyThreshold() const = 0; + + virtual void setVotesThreshold(int votesThreshold) = 0; + virtual int getVotesThreshold() const = 0; + + virtual void setMinRadius(int minRadius) = 0; + virtual int getMinRadius() const = 0; + + virtual void setMaxRadius(int maxRadius) = 0; + virtual int getMaxRadius() const = 0; + + virtual void setMaxCircles(int maxCircles) = 0; + virtual int getMaxCircles() const = 0; + }; + + + +gpu::HoughCirclesDetector::detect +--------------------------------- 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) +.. ocv:function:: void gpu::HoughCirclesDetector::detect(InputArray src, OutputArray circles) :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]_. +.. seealso:: :ocv:func:`HoughCircles` + + + +gpu::createHoughCirclesDetector +------------------------------- +Creates implementation for :ocv:class:`gpu::HoughCirclesDetector` . + +.. ocv:function:: Ptr gpu::createHoughCirclesDetector(float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096) :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 cannyThreshold: The higher threshold of the two passed to 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. @@ -77,20 +214,23 @@ Finds circles in a grayscale image using the Hough transform. :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::createGeneralizedHoughBallard +---------------------------------- +Creates implementation for generalized hough transform from [Ballard1981]_ . + +.. ocv:function:: Ptr gpu::createGeneralizedHoughBallard() -gpu::HoughCirclesDownload -------------------------- -Downloads results from :ocv:func:`gpu::HoughCircles` to host memory. +gpu::createGeneralizedHoughGuil +------------------------------- +Creates implementation for generalized hough transform from [Guil1999]_ . -.. ocv:function:: void gpu::HoughCirclesDownload(const GpuMat& d_circles, OutputArray h_circles) +.. ocv:function:: Ptr gpu::createGeneralizedHoughGuil() - :param d_circles: Result of :ocv:func:`gpu::HoughCircles` . - :param h_circles: Output host array. -.. seealso:: :ocv:func:`gpu::HoughCircles` +.. [Ballard1981] Ballard, D.H. (1981). Generalizing the Hough transform to detect arbitrary shapes. Pattern Recognition 13 (2): 111-122. +.. [Guil1999] 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. diff --git a/modules/gpuimgproc/doc/imgproc.rst b/modules/gpuimgproc/doc/imgproc.rst index cd91afecf..776c339a5 100644 --- a/modules/gpuimgproc/doc/imgproc.rst +++ b/modules/gpuimgproc/doc/imgproc.rst @@ -5,11 +5,72 @@ Image Processing +gpu::CannyEdgeDetector +---------------------- +.. ocv:class:: gpu::CannyEdgeDetector : public Algorithm + +Base class for Canny Edge Detector. :: + + class CV_EXPORTS CannyEdgeDetector : public Algorithm + { + public: + virtual void detect(InputArray image, OutputArray edges) = 0; + virtual void detect(InputArray dx, InputArray dy, OutputArray edges) = 0; + + virtual void setLowThreshold(double low_thresh) = 0; + virtual double getLowThreshold() const = 0; + + virtual void setHighThreshold(double high_thresh) = 0; + virtual double getHighThreshold() const = 0; + + virtual void setAppertureSize(int apperture_size) = 0; + virtual int getAppertureSize() const = 0; + + virtual void setL2Gradient(bool L2gradient) = 0; + virtual bool getL2Gradient() const = 0; + }; + + + +gpu::CannyEdgeDetector::detect +------------------------------ +Finds edges in an image using the [Canny86]_ algorithm. + +.. ocv:function:: void gpu::CannyEdgeDetector::detect(InputArray image, OutputArray edges) + +.. ocv:function:: void gpu::CannyEdgeDetector::detect(InputArray dx, InputArray dy, OutputArray edges) + + :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`` . + + + +gpu::createCannyEdgeDetector +---------------------------- +Creates implementation for :ocv:class:`gpu::CannyEdgeDetector` . + +.. ocv:function:: Ptr gpu::createCannyEdgeDetector(double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false) + + :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`` ). + + + 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() ) +.. ocv:function:: void gpu::meanShiftFiltering(InputArray src, OutputArray 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. @@ -26,10 +87,10 @@ It maps each point of the source image into another point. As a result, you have 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() ) +.. ocv:function:: void gpu::meanShiftProc(InputArray src, OutputArray dstr, OutputArray 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. @@ -48,14 +109,14 @@ Performs a mean-shift procedure and stores information about processed points (t 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)) +.. ocv:function:: void gpu::meanShiftSegmentation(InputArray src, OutputArray 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 dst: Segmented image with the same size and type as ``src`` (host memory). :param sp: Spatial window radius. @@ -67,46 +128,49 @@ Performs a mean-shift segmentation of the source image and eliminates small segm -gpu::MatchTemplateBuf +gpu::TemplateMatching --------------------- -.. ocv:struct:: gpu::MatchTemplateBuf +.. ocv:class:: gpu::TemplateMatching : public Algorithm -Class providing memory buffers for :ocv:func:`gpu::matchTemplate` function, plus it allows to adjust some specific parameters. :: +Base class for Template Matching. :: - struct CV_EXPORTS MatchTemplateBuf + class CV_EXPORTS TemplateMatching : public Algorithm { - Size user_block_size; - GpuMat imagef, templf; - std::vector images; - std::vector image_sums; - std::vector image_sqsums; + public: + virtual void match(InputArray image, InputArray templ, OutputArray result, Stream& stream = Stream::Null()) = 0; }; -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 ----------------------- +gpu::TemplateMatching::match +---------------------------- 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::TemplateMatching::match(InputArray image, InputArray templ, OutputArray result, 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 image: Source image. :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: + + +gpu::createTemplateMatching +--------------------------- +Creates implementation for :ocv:class:`gpu::TemplateMatching` . + +.. ocv:function:: Ptr gpu::createTemplateMatching(int srcType, int method, Size user_block_size = Size()) + + :param srcType: Input source type. ``CV_32F`` and ``CV_8U`` depth images (1..4 channels) are supported for now. + + :param method: Specifies the way to compare the template with the image. + + :param user_block_size: You can use field `user_block_size` to set specific block size. 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. + +The following methods are supported for the ``CV_8U`` depth images for now: * ``CV_TM_SQDIFF`` * ``CV_TM_SQDIFF_NORMED`` @@ -115,7 +179,7 @@ Computes a proximity map for a raster template and an image where the template i * ``CV_TM_CCOEFF`` * ``CV_TM_CCOEFF_NORMED`` - The following methods are supported for the ``CV_32F`` images for now: +The following methods are supported for the ``CV_32F`` images for now: * ``CV_TM_SQDIFF`` * ``CV_TM_CCORR`` @@ -124,45 +188,11 @@ Computes a proximity map for a raster template and an image where the template i -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::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() ) +.. ocv:function:: void gpu::bilateralFilter(InputArray src, OutputArray 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). @@ -178,9 +208,7 @@ Performs bilateral filtering of passed image :param stream: Stream for the asynchronous version. -.. seealso:: - - :ocv:func:`bilateralFilter` +.. seealso:: :ocv:func:`bilateralFilter` @@ -188,7 +216,7 @@ 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()) +.. ocv:function:: void gpu::blendLinear(InputArray img1, InputArray img2, InputArray weights1, InputArray weights2, OutputArray result, Stream& stream = Stream::Null()) :param img1: First image. Supports only ``CV_8U`` and ``CV_32F`` depth. diff --git a/modules/gpuimgproc/include/opencv2/gpuimgproc.hpp b/modules/gpuimgproc/include/opencv2/gpuimgproc.hpp index 3fe9f82f4..f0a0f1260 100644 --- a/modules/gpuimgproc/include/opencv2/gpuimgproc.hpp +++ b/modules/gpuimgproc/include/opencv2/gpuimgproc.hpp @@ -48,16 +48,14 @@ #endif #include "opencv2/core/gpu.hpp" -#include "opencv2/core/base.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/gpufilters.hpp" namespace cv { namespace gpu { /////////////////////////// Color Processing /////////////////////////// //! 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()); +CV_EXPORTS void cvtColor(InputArray src, OutputArray dst, int code, int dcn = 0, Stream& stream = Stream::Null()); enum { @@ -77,67 +75,39 @@ enum COLOR_BayerRG2GRAY_MHT = 262, COLOR_BayerGR2GRAY_MHT = 263 }; -CV_EXPORTS void demosaicing(const GpuMat& src, GpuMat& dst, int code, int dcn = -1, Stream& stream = Stream::Null()); +CV_EXPORTS void demosaicing(InputArray src, OutputArray dst, int code, int dcn = -1, 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()); +CV_EXPORTS void swapChannels(InputOutputArray 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()); +CV_EXPORTS void gammaCorrection(InputArray src, OutputArray dst, bool forward = true, 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()); +CV_EXPORTS void alphaComp(InputArray img1, InputArray img2, OutputArray dst, int alpha_op, Stream& stream = Stream::Null()); ////////////////////////////// Histogram /////////////////////////////// -//! 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()); -CV_EXPORTS void calcHist(const GpuMat& src, GpuMat& hist, GpuMat& buf, Stream& stream = Stream::Null()); +CV_EXPORTS void calcHist(InputArray src, OutputArray 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, Stream& stream = Stream::Null()); -CV_EXPORTS void equalizeHist(const GpuMat& src, GpuMat& dst, GpuMat& hist, GpuMat& buf, Stream& stream = Stream::Null()); +CV_EXPORTS void equalizeHist(InputArray src, OutputArray dst, InputOutputArray buf, Stream& stream = Stream::Null()); + +static inline void equalizeHist(InputArray src, OutputArray dst, Stream& stream = Stream::Null()) +{ + GpuMat buf; + gpu::equalizeHist(src, dst, buf, stream); +} class CV_EXPORTS CLAHE : public cv::CLAHE { @@ -145,194 +115,247 @@ public: using cv::CLAHE::apply; virtual void apply(InputArray src, OutputArray dst, Stream& stream) = 0; }; -CV_EXPORTS Ptr createCLAHE(double clipLimit = 40.0, Size tileGridSize = Size(8, 8)); +CV_EXPORTS Ptr createCLAHE(double clipLimit = 40.0, Size tileGridSize = Size(8, 8)); + +//! Compute levels with even distribution. levels will have 1 row and nLevels cols and CV_32SC1 type. +CV_EXPORTS void evenLevels(OutputArray 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(InputArray src, OutputArray hist, InputOutputArray buf, int histSize, int lowerLevel, int upperLevel, Stream& stream = Stream::Null()); + +static inline void histEven(InputArray src, OutputArray hist, int histSize, int lowerLevel, int upperLevel, Stream& stream = Stream::Null()) +{ + GpuMat buf; + gpu::histEven(src, hist, buf, histSize, lowerLevel, upperLevel, stream); +} + +//! 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(InputArray src, GpuMat hist[4], InputOutputArray buf, int histSize[4], int lowerLevel[4], int upperLevel[4], Stream& stream = Stream::Null()); + +static inline void histEven(InputArray src, GpuMat hist[4], int histSize[4], int lowerLevel[4], int upperLevel[4], Stream& stream = Stream::Null()) +{ + GpuMat buf; + gpu::histEven(src, hist, buf, histSize, lowerLevel, upperLevel, stream); +} + +//! 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(InputArray src, OutputArray hist, InputArray levels, InputOutputArray buf, Stream& stream = Stream::Null()); + +static inline void histRange(InputArray src, OutputArray hist, InputArray levels, Stream& stream = Stream::Null()) +{ + GpuMat buf; + gpu::histRange(src, hist, levels, buf, stream); +} + +//! 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(InputArray src, GpuMat hist[4], const GpuMat levels[4], InputOutputArray buf, Stream& stream = Stream::Null()); + +static inline void histRange(InputArray src, GpuMat hist[4], const GpuMat levels[4], Stream& stream = Stream::Null()) +{ + GpuMat buf; + gpu::histRange(src, hist, levels, buf, stream); +} //////////////////////////////// Canny //////////////////////////////// -struct CV_EXPORTS CannyBuf +class CV_EXPORTS CannyEdgeDetector : public Algorithm { - void create(const Size& image_size, int apperture_size = 3); - void release(); +public: + virtual void detect(InputArray image, OutputArray edges) = 0; + virtual void detect(InputArray dx, InputArray dy, OutputArray edges) = 0; - GpuMat dx, dy; - GpuMat mag; - GpuMat map; - GpuMat st1, st2; - Ptr filterDX, filterDY; + virtual void setLowThreshold(double low_thresh) = 0; + virtual double getLowThreshold() const = 0; + + virtual void setHighThreshold(double high_thresh) = 0; + virtual double getHighThreshold() const = 0; + + virtual void setAppertureSize(int apperture_size) = 0; + virtual int getAppertureSize() const = 0; + + virtual void setL2Gradient(bool L2gradient) = 0; + virtual bool getL2Gradient() const = 0; }; -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); +CV_EXPORTS Ptr createCannyEdgeDetector(double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false); /////////////////////////// Hough Transform //////////////////////////// -struct HoughLinesBuf -{ - GpuMat accum; - GpuMat list; -}; +////////////////////////////////////// +// HoughLines -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()); - -//! 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); - -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 +class CV_EXPORTS HoughLinesDetector : public Algorithm { public: - static Ptr create(int method); + virtual void detect(InputArray src, OutputArray lines) = 0; + virtual void downloadResults(InputArray d_lines, OutputArray h_lines, OutputArray h_votes = noArray()) = 0; - virtual ~GeneralizedHough_GPU(); + virtual void setRho(float rho) = 0; + virtual float getRho() const = 0; - //! 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)); + virtual void setTheta(float theta) = 0; + virtual float getTheta() const = 0; - //! 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); + virtual void setThreshold(int threshold) = 0; + virtual int getThreshold() const = 0; - void download(const GpuMat& d_positions, OutputArray h_positions, OutputArray h_votes = noArray()); + virtual void setDoSort(bool doSort) = 0; + virtual bool getDoSort() const = 0; - 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_; + virtual void setMaxLines(int maxLines) = 0; + virtual int getMaxLines() const = 0; }; +CV_EXPORTS Ptr createHoughLinesDetector(float rho, float theta, int threshold, bool doSort = false, int maxLines = 4096); + + +////////////////////////////////////// +// HoughLinesP + +//! finds line segments in the black-n-white image using probabalistic Hough transform +class CV_EXPORTS HoughSegmentDetector : public Algorithm +{ +public: + virtual void detect(InputArray src, OutputArray lines) = 0; + + virtual void setRho(float rho) = 0; + virtual float getRho() const = 0; + + virtual void setTheta(float theta) = 0; + virtual float getTheta() const = 0; + + virtual void setMinLineLength(int minLineLength) = 0; + virtual int getMinLineLength() const = 0; + + virtual void setMaxLineGap(int maxLineGap) = 0; + virtual int getMaxLineGap() const = 0; + + virtual void setMaxLines(int maxLines) = 0; + virtual int getMaxLines() const = 0; +}; + +CV_EXPORTS Ptr createHoughSegmentDetector(float rho, float theta, int minLineLength, int maxLineGap, int maxLines = 4096); + +////////////////////////////////////// +// HoughCircles + +class CV_EXPORTS HoughCirclesDetector : public Algorithm +{ +public: + virtual void detect(InputArray src, OutputArray circles) = 0; + + virtual void setDp(float dp) = 0; + virtual float getDp() const = 0; + + virtual void setMinDist(float minDist) = 0; + virtual float getMinDist() const = 0; + + virtual void setCannyThreshold(int cannyThreshold) = 0; + virtual int getCannyThreshold() const = 0; + + virtual void setVotesThreshold(int votesThreshold) = 0; + virtual int getVotesThreshold() const = 0; + + virtual void setMinRadius(int minRadius) = 0; + virtual int getMinRadius() const = 0; + + virtual void setMaxRadius(int maxRadius) = 0; + virtual int getMaxRadius() const = 0; + + virtual void setMaxCircles(int maxCircles) = 0; + virtual int getMaxCircles() const = 0; +}; + +CV_EXPORTS Ptr createHoughCirclesDetector(float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096); + +////////////////////////////////////// +// GeneralizedHough + +//! Ballard, D.H. (1981). Generalizing the Hough transform to detect arbitrary shapes. Pattern Recognition 13 (2): 111-122. +//! Detects position only without traslation and rotation +CV_EXPORTS Ptr createGeneralizedHoughBallard(); + +//! 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. +//! Detects position, traslation and rotation +CV_EXPORTS Ptr createGeneralizedHoughGuil(); + ////////////////////////// Corners Detection /////////////////////////// -//! 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()); - -////////////////////////// Feature Detection /////////////////////////// - -class CV_EXPORTS GoodFeaturesToTrackDetector_GPU +class CV_EXPORTS CornernessCriteria : public Algorithm { 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_; + virtual void compute(InputArray src, OutputArray dst, Stream& stream = Stream::Null()) = 0; }; -inline GoodFeaturesToTrackDetector_GPU::GoodFeaturesToTrackDetector_GPU(int maxCorners_, double qualityLevel_, double minDistance_, - int blockSize_, bool useHarrisDetector_, double harrisK_) +//! computes Harris cornerness criteria at each image pixel +CV_EXPORTS Ptr createHarrisCorner(int srcType, int blockSize, int ksize, double k, int borderType = BORDER_REFLECT101); + +//! computes minimum eigen value of 2x2 derivative covariation matrix at each pixel - the cornerness criteria +CV_EXPORTS Ptr createMinEigenValCorner(int srcType, int blockSize, int ksize, int borderType = BORDER_REFLECT101); + +////////////////////////// Corners Detection /////////////////////////// + +class CV_EXPORTS CornersDetector : public Algorithm { - maxCorners = maxCorners_; - qualityLevel = qualityLevel_; - minDistance = minDistance_; - blockSize = blockSize_; - useHarrisDetector = useHarrisDetector_; - harrisK = harrisK_; -} +public: + //! return 1 rows matrix with CV_32FC2 type + virtual void detect(InputArray image, OutputArray corners, InputArray mask = noArray()) = 0; +}; + +CV_EXPORTS Ptr createGoodFeaturesToTrackDetector(int srcType, int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 0.0, + int blockSize = 3, bool useHarrisDetector = false, double harrisK = 0.04); ///////////////////////////// Mean Shift ////////////////////////////// //! Does mean shift filtering on GPU. -CV_EXPORTS void meanShiftFiltering(const GpuMat& src, GpuMat& dst, int sp, int sr, +CV_EXPORTS void meanShiftFiltering(InputArray src, OutputArray 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, +CV_EXPORTS void meanShiftProc(InputArray src, OutputArray dstr, OutputArray 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, +CV_EXPORTS void meanShiftSegmentation(InputArray src, OutputArray dst, int sp, int sr, int minsize, TermCriteria criteria = TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1)); /////////////////////////// Match Template //////////////////////////// -struct CV_EXPORTS MatchTemplateBuf +//! computes the proximity map for the raster template and the image where the template is searched for +class CV_EXPORTS TemplateMatching : public Algorithm { - Size user_block_size; - GpuMat imagef, templf; - std::vector images; - std::vector image_sums; - std::vector image_sqsums; +public: + virtual void match(InputArray image, InputArray templ, OutputArray result, Stream& stream = Stream::Null()) = 0; }; -//! 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()); +CV_EXPORTS Ptr createTemplateMatching(int srcType, int method, Size user_block_size = Size()); ////////////////////////// Bilateral Filter /////////////////////////// //! Performa bilateral filtering of passsed image -CV_EXPORTS void bilateralFilter(const GpuMat& src, GpuMat& dst, int kernel_size, float sigma_color, float sigma_spatial, +CV_EXPORTS void bilateralFilter(InputArray src, OutputArray dst, int kernel_size, float sigma_color, float sigma_spatial, int borderMode = BORDER_DEFAULT, Stream& stream = Stream::Null()); ///////////////////////////// Blending //////////////////////////////// //! 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()); +CV_EXPORTS void blendLinear(InputArray img1, InputArray img2, InputArray weights1, InputArray weights2, + OutputArray result, Stream& stream = Stream::Null()); }} // namespace cv { namespace gpu { diff --git a/modules/gpuimgproc/perf/perf_canny.cpp b/modules/gpuimgproc/perf/perf_canny.cpp index ce6db2bb3..2bbf70a49 100644 --- a/modules/gpuimgproc/perf/perf_canny.cpp +++ b/modules/gpuimgproc/perf/perf_canny.cpp @@ -70,9 +70,10 @@ PERF_TEST_P(Image_AppertureSz_L2gradient, Canny, { 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); + cv::Ptr canny = cv::gpu::createCannyEdgeDetector(low_thresh, high_thresh, apperture_size, useL2gradient); + + TEST_CYCLE() canny->detect(d_image, dst); GPU_SANITY_CHECK(dst); } diff --git a/modules/gpuimgproc/perf/perf_corners.cpp b/modules/gpuimgproc/perf/perf_corners.cpp index 28e8806e5..a0c1f8d30 100644 --- a/modules/gpuimgproc/perf/perf_corners.cpp +++ b/modules/gpuimgproc/perf/perf_corners.cpp @@ -75,11 +75,10 @@ PERF_TEST_P(Image_Type_Border_BlockSz_ApertureSz, CornerHarris, { 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); + cv::Ptr harris = cv::gpu::createHarrisCorner(img.type(), blockSize, apertureSize, k, borderMode); + + TEST_CYCLE() harris->compute(d_img, dst); GPU_SANITY_CHECK(dst, 1e-4); } @@ -118,11 +117,10 @@ PERF_TEST_P(Image_Type_Border_BlockSz_ApertureSz, CornerMinEigenVal, { 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); + cv::Ptr minEigenVal = cv::gpu::createMinEigenValCorner(img.type(), blockSize, apertureSize, borderMode); + + TEST_CYCLE() minEigenVal->compute(d_img, dst); GPU_SANITY_CHECK(dst, 1e-4); } diff --git a/modules/gpuimgproc/perf/perf_gftt.cpp b/modules/gpuimgproc/perf/perf_gftt.cpp index 982182d17..ed8d6ac16 100644 --- a/modules/gpuimgproc/perf/perf_gftt.cpp +++ b/modules/gpuimgproc/perf/perf_gftt.cpp @@ -66,12 +66,12 @@ PERF_TEST_P(Image_MinDistance, GoodFeaturesToTrack, if (PERF_RUN_GPU()) { - cv::gpu::GoodFeaturesToTrackDetector_GPU d_detector(maxCorners, qualityLevel, minDistance); + cv::Ptr d_detector = cv::gpu::createGoodFeaturesToTrackDetector(image.type(), maxCorners, qualityLevel, minDistance); const cv::gpu::GpuMat d_image(image); cv::gpu::GpuMat pts; - TEST_CYCLE() d_detector(d_image, pts); + TEST_CYCLE() d_detector->detect(d_image, pts); GPU_SANITY_CHECK(pts); } diff --git a/modules/gpuimgproc/perf/perf_histogram.cpp b/modules/gpuimgproc/perf/perf_histogram.cpp index 51f7416f9..d8def54ff 100644 --- a/modules/gpuimgproc/perf/perf_histogram.cpp +++ b/modules/gpuimgproc/perf/perf_histogram.cpp @@ -167,10 +167,9 @@ PERF_TEST_P(Sz, EqualizeHist, { 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); + TEST_CYCLE() cv::gpu::equalizeHist(d_src, dst, d_buf); GPU_SANITY_CHECK(dst); } diff --git a/modules/gpuimgproc/perf/perf_hough.cpp b/modules/gpuimgproc/perf/perf_hough.cpp index a4aac0d02..cce8e7432 100644 --- a/modules/gpuimgproc/perf/perf_hough.cpp +++ b/modules/gpuimgproc/perf/perf_hough.cpp @@ -103,9 +103,10 @@ PERF_TEST_P(Sz, HoughLines, { 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::Ptr hough = cv::gpu::createHoughLinesDetector(rho, theta, threshold); + + TEST_CYCLE() hough->detect(d_src, d_lines); cv::Mat gpu_lines(d_lines.row(0)); cv::Vec2f* begin = gpu_lines.ptr(0); @@ -151,9 +152,10 @@ PERF_TEST_P(Image, HoughLinesP, { 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::Ptr hough = cv::gpu::createHoughSegmentDetector(rho, theta, minLineLenght, maxLineGap); + + TEST_CYCLE() hough->detect(d_mask, d_lines); cv::Mat gpu_lines(d_lines); cv::Vec4i* begin = gpu_lines.ptr(); @@ -201,9 +203,10 @@ PERF_TEST_P(Sz_Dp_MinDist, HoughCircles, { 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::Ptr houghCircles = cv::gpu::createHoughCirclesDetector(dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius); + + TEST_CYCLE() houghCircles->detect(d_src, d_circles); cv::Mat gpu_circles(d_circles); cv::Vec3f* begin = gpu_circles.ptr(0); @@ -224,23 +227,59 @@ PERF_TEST_P(Sz_Dp_MinDist, HoughCircles, ////////////////////////////////////////////////////////////////////// // GeneralizedHough -enum { GHT_POSITION = cv::GeneralizedHough::GHT_POSITION, - GHT_SCALE = cv::GeneralizedHough::GHT_SCALE, - GHT_ROTATION = cv::GeneralizedHough::GHT_ROTATION - }; - -CV_FLAGS(GHMethod, GHT_POSITION, GHT_SCALE, GHT_ROTATION); - -DEF_PARAM_TEST(Method_Sz, GHMethod, cv::Size); - -PERF_TEST_P(Method_Sz, GeneralizedHough, - Combine(Values(GHMethod(GHT_POSITION), GHMethod(GHT_POSITION | GHT_SCALE), GHMethod(GHT_POSITION | GHT_ROTATION), GHMethod(GHT_POSITION | GHT_SCALE | GHT_ROTATION)), - GPU_TYPICAL_MAT_SIZES)) +PERF_TEST_P(Sz, GeneralizedHoughBallard, GPU_TYPICAL_MAT_SIZES) { declare.time(10); - const int method = GET_PARAM(0); - const cv::Size imageSize = GET_PARAM(1); + const cv::Size imageSize = GetParam(); + + 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::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()) + { + cv::Ptr alg = cv::gpu::createGeneralizedHoughBallard(); + + const cv::gpu::GpuMat d_edges(edges); + const cv::gpu::GpuMat d_dx(dx); + const cv::gpu::GpuMat d_dy(dy); + cv::gpu::GpuMat positions; + + alg->setTemplate(cv::gpu::GpuMat(templ)); + + TEST_CYCLE() alg->detect(d_edges, d_dx, d_dy, positions); + + GPU_SANITY_CHECK(positions); + } + else + { + cv::Ptr alg = cv::createGeneralizedHoughBallard(); + + cv::Mat positions; + + alg->setTemplate(templ); + + TEST_CYCLE() alg->detect(edges, dx, dy, positions); + + CPU_SANITY_CHECK(positions); + } +} + +PERF_TEST_P(Sz, GeneralizedHoughGuil, GPU_TYPICAL_MAT_SIZES) +{ + declare.time(10); + + const cv::Size imageSize = GetParam(); const cv::Mat templ = readImage("cv/shared/templ.png", cv::IMREAD_GRAYSCALE); ASSERT_FALSE(templ.empty()); @@ -278,39 +317,32 @@ PERF_TEST_P(Method_Sz, GeneralizedHough, if (PERF_RUN_GPU()) { + cv::Ptr alg = cv::gpu::createGeneralizedHoughGuil(); + alg->setMaxAngle(90.0); + alg->setAngleStep(2.0); + 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::gpu::GpuMat positions; - cv::Ptr d_hough = cv::gpu::GeneralizedHough_GPU::create(method); - if (method & GHT_ROTATION) - { - d_hough->set("maxAngle", 90.0); - d_hough->set("angleStep", 2.0); - } + alg->setTemplate(cv::gpu::GpuMat(templ)); - d_hough->setTemplate(cv::gpu::GpuMat(templ)); + TEST_CYCLE() alg->detect(d_edges, d_dx, d_dy, positions); - 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::Ptr alg = cv::createGeneralizedHoughGuil(); + alg->setMaxAngle(90.0); + alg->setAngleStep(2.0); + cv::Mat positions; - cv::Ptr hough = cv::GeneralizedHough::create(method); - if (method & GHT_ROTATION) - { - hough->set("maxAngle", 90.0); - hough->set("angleStep", 2.0); - } + alg->setTemplate(templ); - hough->setTemplate(templ); - - TEST_CYCLE() hough->detect(edges, dx, dy, positions); + TEST_CYCLE() alg->detect(edges, dx, dy, positions); CPU_SANITY_CHECK(positions); } diff --git a/modules/gpuimgproc/perf/perf_main.cpp b/modules/gpuimgproc/perf/perf_main.cpp index 6b3bec5f8..8eb27a27b 100644 --- a/modules/gpuimgproc/perf/perf_main.cpp +++ b/modules/gpuimgproc/perf/perf_main.cpp @@ -44,4 +44,4 @@ using namespace perf; -CV_PERF_TEST_MAIN(gpuimgproc, printCudaInfo()) +CV_PERF_TEST_CUDA_MAIN(gpuimgproc) diff --git a/modules/gpuimgproc/perf/perf_match_template.cpp b/modules/gpuimgproc/perf/perf_match_template.cpp index f3af14914..35f36596c 100644 --- a/modules/gpuimgproc/perf/perf_match_template.cpp +++ b/modules/gpuimgproc/perf/perf_match_template.cpp @@ -76,7 +76,9 @@ PERF_TEST_P(Sz_TemplateSz_Cn_Method, MatchTemplate8U, const cv::gpu::GpuMat d_templ(templ); cv::gpu::GpuMat dst; - TEST_CYCLE() cv::gpu::matchTemplate(d_image, d_templ, dst, method); + cv::Ptr alg = cv::gpu::createTemplateMatching(image.type(), method); + + TEST_CYCLE() alg->match(d_image, d_templ, dst); GPU_SANITY_CHECK(dst, 1e-5, ERROR_RELATIVE); } @@ -116,7 +118,9 @@ PERF_TEST_P(Sz_TemplateSz_Cn_Method, MatchTemplate32F, const cv::gpu::GpuMat d_templ(templ); cv::gpu::GpuMat dst; - TEST_CYCLE() cv::gpu::matchTemplate(d_image, d_templ, dst, method); + cv::Ptr alg = cv::gpu::createTemplateMatching(image.type(), method); + + TEST_CYCLE() alg->match(d_image, d_templ, dst); GPU_SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); } diff --git a/modules/gpuimgproc/perf/perf_precomp.cpp b/modules/gpuimgproc/perf/perf_precomp.cpp deleted file mode 100644 index 81f16e8f1..000000000 --- a/modules/gpuimgproc/perf/perf_precomp.cpp +++ /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 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" diff --git a/modules/gpuimgproc/src/bilateral_filter.cpp b/modules/gpuimgproc/src/bilateral_filter.cpp index c95dbe4f5..b9d0b811e 100644 --- a/modules/gpuimgproc/src/bilateral_filter.cpp +++ b/modules/gpuimgproc/src/bilateral_filter.cpp @@ -47,7 +47,7 @@ using namespace cv::gpu; #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) -void cv::gpu::bilateralFilter(const GpuMat&, GpuMat&, int, float, float, int, Stream&) { throw_no_cuda(); } +void cv::gpu::bilateralFilter(InputArray, OutputArray, int, float, float, int, Stream&) { throw_no_cuda(); } #else @@ -60,7 +60,7 @@ namespace cv { namespace gpu { namespace cudev } }}} -void cv::gpu::bilateralFilter(const GpuMat& src, GpuMat& dst, int kernel_size, float sigma_color, float sigma_spatial, int borderMode, Stream& s) +void cv::gpu::bilateralFilter(InputArray _src, OutputArray _dst, int kernel_size, float sigma_color, float sigma_spatial, int borderMode, Stream& stream) { using cv::gpu::cudev::imgproc::bilateral_filter_gpu; @@ -79,18 +79,21 @@ void cv::gpu::bilateralFilter(const GpuMat& src, GpuMat& dst, int kernel_size, f sigma_color = (sigma_color <= 0 ) ? 1 : sigma_color; sigma_spatial = (sigma_spatial <= 0 ) ? 1 : sigma_spatial; - int radius = (kernel_size <= 0) ? cvRound(sigma_spatial*1.5) : kernel_size/2; kernel_size = std::max(radius, 1)*2 + 1; - CV_Assert(src.depth() <= CV_32F && src.channels() <= 4); + GpuMat src = _src.getGpuMat(); + + CV_Assert( src.depth() <= CV_32F && src.channels() <= 4 ); + CV_Assert( borderMode == BORDER_REFLECT101 || borderMode == BORDER_REPLICATE || borderMode == BORDER_CONSTANT || borderMode == BORDER_REFLECT || borderMode == BORDER_WRAP ); + const func_t func = funcs[src.depth()][src.channels() - 1]; - CV_Assert(func != 0); + CV_Assert( func != 0 ); - CV_Assert(borderMode == BORDER_REFLECT101 || borderMode == BORDER_REPLICATE || borderMode == BORDER_CONSTANT || borderMode == BORDER_REFLECT || borderMode == BORDER_WRAP); + _dst.create(src.size(), src.type()); + GpuMat dst = _dst.getGpuMat(); - dst.create(src.size(), src.type()); - func(src, dst, kernel_size, sigma_spatial, sigma_color, borderMode, StreamAccessor::getStream(s)); + func(src, dst, kernel_size, sigma_spatial, sigma_color, borderMode, StreamAccessor::getStream(stream)); } #endif diff --git a/modules/gpuimgproc/src/blend.cpp b/modules/gpuimgproc/src/blend.cpp index e92e37945..71c72a715 100644 --- a/modules/gpuimgproc/src/blend.cpp +++ b/modules/gpuimgproc/src/blend.cpp @@ -47,7 +47,7 @@ using namespace cv::gpu; #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) -void cv::gpu::blendLinear(const GpuMat&, const GpuMat&, const GpuMat&, const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); } +void cv::gpu::blendLinear(InputArray, InputArray, InputArray, InputArray, OutputArray, Stream&) { throw_no_cuda(); } #else @@ -67,21 +67,28 @@ namespace cv { namespace gpu { namespace cudev using namespace ::cv::gpu::cudev::blend; -void cv::gpu::blendLinear(const GpuMat& img1, const GpuMat& img2, const GpuMat& weights1, const GpuMat& weights2, - GpuMat& result, Stream& stream) +void cv::gpu::blendLinear(InputArray _img1, InputArray _img2, InputArray _weights1, InputArray _weights2, + OutputArray _result, Stream& stream) { - CV_Assert(img1.size() == img2.size()); - CV_Assert(img1.type() == img2.type()); - CV_Assert(weights1.size() == img1.size()); - CV_Assert(weights2.size() == img2.size()); - CV_Assert(weights1.type() == CV_32F); - CV_Assert(weights2.type() == CV_32F); + GpuMat img1 = _img1.getGpuMat(); + GpuMat img2 = _img2.getGpuMat(); + + GpuMat weights1 = _weights1.getGpuMat(); + GpuMat weights2 = _weights2.getGpuMat(); + + CV_Assert( img1.size() == img2.size() ); + CV_Assert( img1.type() == img2.type() ); + CV_Assert( weights1.size() == img1.size() ); + CV_Assert( weights2.size() == img2.size() ); + CV_Assert( weights1.type() == CV_32FC1 ); + CV_Assert( weights2.type() == CV_32FC1 ); const Size size = img1.size(); const int depth = img1.depth(); const int cn = img1.channels(); - result.create(size, CV_MAKE_TYPE(depth, cn)); + _result.create(size, CV_MAKE_TYPE(depth, cn)); + GpuMat result = _result.getGpuMat(); switch (depth) { diff --git a/modules/gpuimgproc/src/canny.cpp b/modules/gpuimgproc/src/canny.cpp index 9a3357564..17f03950f 100644 --- a/modules/gpuimgproc/src/canny.cpp +++ b/modules/gpuimgproc/src/canny.cpp @@ -47,46 +47,10 @@ using namespace cv::gpu; #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) -void cv::gpu::Canny(const GpuMat&, GpuMat&, double, double, int, bool) { throw_no_cuda(); } -void cv::gpu::Canny(const GpuMat&, CannyBuf&, GpuMat&, double, double, int, bool) { throw_no_cuda(); } -void cv::gpu::Canny(const GpuMat&, const GpuMat&, GpuMat&, double, double, bool) { throw_no_cuda(); } -void cv::gpu::Canny(const GpuMat&, const GpuMat&, CannyBuf&, GpuMat&, double, double, bool) { throw_no_cuda(); } -void cv::gpu::CannyBuf::create(const Size&, int) { throw_no_cuda(); } -void cv::gpu::CannyBuf::release() { throw_no_cuda(); } +Ptr cv::gpu::createCannyEdgeDetector(double, double, int, bool) { throw_no_cuda(); return Ptr(); } #else /* !defined (HAVE_CUDA) */ -void cv::gpu::CannyBuf::create(const Size& image_size, int apperture_size) -{ - if (apperture_size > 0) - { - ensureSizeIsEnough(image_size, CV_32SC1, dx); - ensureSizeIsEnough(image_size, CV_32SC1, dy); - - if (apperture_size != 3) - { - filterDX = createDerivFilter(CV_8UC1, CV_32S, 1, 0, apperture_size, false, 1, BORDER_REPLICATE); - filterDY = createDerivFilter(CV_8UC1, CV_32S, 0, 1, apperture_size, false, 1, BORDER_REPLICATE); - } - } - - ensureSizeIsEnough(image_size, CV_32FC1, mag); - ensureSizeIsEnough(image_size, CV_32SC1, map); - - ensureSizeIsEnough(1, image_size.area(), CV_16UC2, st1); - ensureSizeIsEnough(1, image_size.area(), CV_16UC2, st2); -} - -void cv::gpu::CannyBuf::release() -{ - dx.release(); - dy.release(); - mag.release(); - map.release(); - st1.release(); - st2.release(); -} - namespace canny { void calcMagnitude(PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzi dx, PtrStepSzi dy, PtrStepSzf mag, bool L2Grad); @@ -103,84 +67,168 @@ namespace canny namespace { - void CannyCaller(const GpuMat& dx, const GpuMat& dy, CannyBuf& buf, GpuMat& dst, float low_thresh, float high_thresh) + class CannyImpl : public CannyEdgeDetector { - using namespace canny; + public: + CannyImpl(double low_thresh, double high_thresh, int apperture_size, bool L2gradient) : + low_thresh_(low_thresh), high_thresh_(high_thresh), apperture_size_(apperture_size), L2gradient_(L2gradient) + { + old_apperture_size_ = -1; + } - buf.map.setTo(Scalar::all(0)); - calcMap(dx, dy, buf.mag, buf.map, low_thresh, high_thresh); + void detect(InputArray image, OutputArray edges); + void detect(InputArray dx, InputArray dy, OutputArray edges); - edgesHysteresisLocal(buf.map, buf.st1.ptr()); + void setLowThreshold(double low_thresh) { low_thresh_ = low_thresh; } + double getLowThreshold() const { return low_thresh_; } - edgesHysteresisGlobal(buf.map, buf.st1.ptr(), buf.st2.ptr()); + void setHighThreshold(double high_thresh) { high_thresh_ = high_thresh; } + double getHighThreshold() const { return high_thresh_; } - getEdges(buf.map, dst); + void setAppertureSize(int apperture_size) { apperture_size_ = apperture_size; } + int getAppertureSize() const { return apperture_size_; } + + void setL2Gradient(bool L2gradient) { L2gradient_ = L2gradient; } + bool getL2Gradient() const { return L2gradient_; } + + void write(FileStorage& fs) const + { + fs << "name" << "Canny_GPU" + << "low_thresh" << low_thresh_ + << "high_thresh" << high_thresh_ + << "apperture_size" << apperture_size_ + << "L2gradient" << L2gradient_; + } + + void read(const FileNode& fn) + { + CV_Assert( String(fn["name"]) == "Canny_GPU" ); + low_thresh_ = (double)fn["low_thresh"]; + high_thresh_ = (double)fn["high_thresh"]; + apperture_size_ = (int)fn["apperture_size"]; + L2gradient_ = (int)fn["L2gradient"] != 0; + } + + private: + void createBuf(Size image_size); + void CannyCaller(GpuMat& edges); + + double low_thresh_; + double high_thresh_; + int apperture_size_; + bool L2gradient_; + + GpuMat dx_, dy_; + GpuMat mag_; + GpuMat map_; + GpuMat st1_, st2_; +#ifdef HAVE_OPENCV_GPUFILTERS + Ptr filterDX_, filterDY_; +#endif + int old_apperture_size_; + }; + + void CannyImpl::detect(InputArray _image, OutputArray _edges) + { + GpuMat image = _image.getGpuMat(); + + CV_Assert( image.type() == CV_8UC1 ); + CV_Assert( deviceSupports(SHARED_ATOMICS) ); + + if (low_thresh_ > high_thresh_) + std::swap(low_thresh_, high_thresh_); + + createBuf(image.size()); + + _edges.create(image.size(), CV_8UC1); + GpuMat edges = _edges.getGpuMat(); + + if (apperture_size_ == 3) + { + Size wholeSize; + Point ofs; + image.locateROI(wholeSize, ofs); + GpuMat srcWhole(wholeSize, image.type(), image.datastart, image.step); + + canny::calcMagnitude(srcWhole, ofs.x, ofs.y, dx_, dy_, mag_, L2gradient_); + } + else + { +#ifndef HAVE_OPENCV_GPUFILTERS + throw_no_cuda(); +#else + filterDX_->apply(image, dx_); + filterDY_->apply(image, dy_); + + canny::calcMagnitude(dx_, dy_, mag_, L2gradient_); +#endif + } + + CannyCaller(edges); + } + + void CannyImpl::detect(InputArray _dx, InputArray _dy, OutputArray _edges) + { + GpuMat dx = _dx.getGpuMat(); + GpuMat dy = _dy.getGpuMat(); + + CV_Assert( dx.type() == CV_32SC1 ); + CV_Assert( dy.type() == dx.type() && dy.size() == dx.size() ); + CV_Assert( deviceSupports(SHARED_ATOMICS) ); + + dx.copyTo(dx_); + dy.copyTo(dy_); + + if (low_thresh_ > high_thresh_) + std::swap(low_thresh_, high_thresh_); + + createBuf(dx.size()); + + _edges.create(dx.size(), CV_8UC1); + GpuMat edges = _edges.getGpuMat(); + + canny::calcMagnitude(dx_, dy_, mag_, L2gradient_); + + CannyCaller(edges); + } + + void CannyImpl::createBuf(Size image_size) + { + ensureSizeIsEnough(image_size, CV_32SC1, dx_); + ensureSizeIsEnough(image_size, CV_32SC1, dy_); + +#ifdef HAVE_OPENCV_GPUFILTERS + if (apperture_size_ != 3 && apperture_size_ != old_apperture_size_) + { + filterDX_ = gpu::createDerivFilter(CV_8UC1, CV_32S, 1, 0, apperture_size_, false, 1, BORDER_REPLICATE); + filterDY_ = gpu::createDerivFilter(CV_8UC1, CV_32S, 0, 1, apperture_size_, false, 1, BORDER_REPLICATE); + old_apperture_size_ = apperture_size_; + } +#endif + + ensureSizeIsEnough(image_size, CV_32FC1, mag_); + ensureSizeIsEnough(image_size, CV_32SC1, map_); + + ensureSizeIsEnough(1, image_size.area(), CV_16UC2, st1_); + ensureSizeIsEnough(1, image_size.area(), CV_16UC2, st2_); + } + + void CannyImpl::CannyCaller(GpuMat& edges) + { + map_.setTo(Scalar::all(0)); + canny::calcMap(dx_, dy_, mag_, map_, static_cast(low_thresh_), static_cast(high_thresh_)); + + canny::edgesHysteresisLocal(map_, st1_.ptr()); + + canny::edgesHysteresisGlobal(map_, st1_.ptr(), st2_.ptr()); + + canny::getEdges(map_, edges); } } -void cv::gpu::Canny(const GpuMat& src, GpuMat& dst, double low_thresh, double high_thresh, int apperture_size, bool L2gradient) +Ptr cv::gpu::createCannyEdgeDetector(double low_thresh, double high_thresh, int apperture_size, bool L2gradient) { - CannyBuf buf; - Canny(src, buf, dst, low_thresh, high_thresh, apperture_size, L2gradient); -} - -void cv::gpu::Canny(const GpuMat& src, CannyBuf& buf, GpuMat& dst, double low_thresh, double high_thresh, int apperture_size, bool L2gradient) -{ - using namespace canny; - - CV_Assert(src.type() == CV_8UC1); - - if (!deviceSupports(SHARED_ATOMICS)) - CV_Error(cv::Error::StsNotImplemented, "The device doesn't support shared atomics"); - - if( low_thresh > high_thresh ) - std::swap( low_thresh, high_thresh); - - dst.create(src.size(), CV_8U); - buf.create(src.size(), apperture_size); - - if (apperture_size == 3) - { - Size wholeSize; - Point ofs; - src.locateROI(wholeSize, ofs); - GpuMat srcWhole(wholeSize, src.type(), src.datastart, src.step); - - calcMagnitude(srcWhole, ofs.x, ofs.y, buf.dx, buf.dy, buf.mag, L2gradient); - } - else - { - buf.filterDX->apply(src, buf.dx); - buf.filterDY->apply(src, buf.dy); - - calcMagnitude(buf.dx, buf.dy, buf.mag, L2gradient); - } - - CannyCaller(buf.dx, buf.dy, buf, dst, static_cast(low_thresh), static_cast(high_thresh)); -} - -void cv::gpu::Canny(const GpuMat& dx, const GpuMat& dy, GpuMat& dst, double low_thresh, double high_thresh, bool L2gradient) -{ - CannyBuf buf; - Canny(dx, dy, buf, dst, low_thresh, high_thresh, L2gradient); -} - -void cv::gpu::Canny(const GpuMat& dx, const GpuMat& dy, CannyBuf& buf, GpuMat& dst, double low_thresh, double high_thresh, bool L2gradient) -{ - using namespace canny; - - CV_Assert(TargetArchs::builtWith(SHARED_ATOMICS) && DeviceInfo().supports(SHARED_ATOMICS)); - CV_Assert(dx.type() == CV_32SC1 && dy.type() == CV_32SC1 && dx.size() == dy.size()); - - if( low_thresh > high_thresh ) - std::swap( low_thresh, high_thresh); - - dst.create(dx.size(), CV_8U); - buf.create(dx.size(), -1); - - calcMagnitude(dx, dy, buf.mag, L2gradient); - - CannyCaller(dx, dy, buf, dst, static_cast(low_thresh), static_cast(high_thresh)); + return makePtr(low_thresh, high_thresh, apperture_size, L2gradient); } #endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpuimgproc/src/color.cpp b/modules/gpuimgproc/src/color.cpp index c1af7ce75..3d714b628 100644 --- a/modules/gpuimgproc/src/color.cpp +++ b/modules/gpuimgproc/src/color.cpp @@ -47,15 +47,16 @@ using namespace cv::gpu; #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) -void cv::gpu::cvtColor(const GpuMat&, GpuMat&, int, int, Stream&) { throw_no_cuda(); } +void cv::gpu::cvtColor(InputArray, OutputArray, int, int, Stream&) { throw_no_cuda(); } -void cv::gpu::demosaicing(const GpuMat&, GpuMat&, int, int, Stream&) { throw_no_cuda(); } +void cv::gpu::demosaicing(InputArray, OutputArray, int, int, Stream&) { throw_no_cuda(); } -void cv::gpu::swapChannels(GpuMat&, const int[], Stream&) { throw_no_cuda(); } +void cv::gpu::swapChannels(InputOutputArray, const int[], Stream&) { throw_no_cuda(); } -void cv::gpu::gammaCorrection(const GpuMat&, GpuMat&, bool, Stream&) { throw_no_cuda(); } +void cv::gpu::gammaCorrection(InputArray, OutputArray, bool, Stream&) { throw_no_cuda(); } + +void cv::gpu::alphaComp(InputArray, InputArray, OutputArray, int, Stream&) { throw_no_cuda(); } -void cv::gpu::alphaComp(const GpuMat&, const GpuMat&, GpuMat&, int, Stream&) { throw_no_cuda(); } #else /* !defined (HAVE_CUDA) */ @@ -80,363 +81,459 @@ 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) + void bgr_to_rgb(InputArray _src, OutputArray _dst, int, Stream& stream) { using namespace cv::gpu::cudev; 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), 3)); + CV_Assert( src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F ); + CV_Assert( src.channels() == 3 ); + + _dst.create(src.size(), CV_MAKE_TYPE(src.depth(), 3)); + GpuMat dst = _dst.getGpuMat(); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } - void bgr_to_bgra(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr_to_bgra(InputArray _src, OutputArray _dst, int, Stream& stream) { using namespace cv::gpu::cudev; 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), 4)); + CV_Assert( src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F ); + CV_Assert( src.channels() == 3 ); + + _dst.create(src.size(), CV_MAKE_TYPE(src.depth(), 4)); + GpuMat dst = _dst.getGpuMat(); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } - void bgr_to_rgba(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr_to_rgba(InputArray _src, OutputArray _dst, int, Stream& stream) { using namespace cv::gpu::cudev; 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), 4)); + CV_Assert( src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F ); + CV_Assert( src.channels() == 3 ); + + _dst.create(src.size(), CV_MAKE_TYPE(src.depth(), 4)); + GpuMat dst = _dst.getGpuMat(); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } - void bgra_to_bgr(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgra_to_bgr(InputArray _src, OutputArray _dst, int, Stream& stream) { using namespace cv::gpu::cudev; 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), 3)); + CV_Assert( src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F ); + CV_Assert( src.channels() == 4 ); + + _dst.create(src.size(), CV_MAKE_TYPE(src.depth(), 3)); + GpuMat dst = _dst.getGpuMat(); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } - void bgra_to_rgb(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgra_to_rgb(InputArray _src, OutputArray _dst, int, Stream& stream) { using namespace cv::gpu::cudev; 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), 3)); + CV_Assert( src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F ); + CV_Assert( src.channels() == 4 ); + + _dst.create(src.size(), CV_MAKE_TYPE(src.depth(), 3)); + GpuMat dst = _dst.getGpuMat(); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } - void bgra_to_rgba(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgra_to_rgba(InputArray _src, OutputArray _dst, int, Stream& stream) { using namespace cv::gpu::cudev; 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), 4)); + CV_Assert( src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F ); + CV_Assert( src.channels() == 4 ); + + _dst.create(src.size(), CV_MAKE_TYPE(src.depth(), 4)); + GpuMat dst = _dst.getGpuMat(); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } - void bgr_to_bgr555(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr_to_bgr555(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 3); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC2); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 3 ); - cudev::bgr_to_bgr555(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC2); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgr_to_bgr555(src, dst, StreamAccessor::getStream(stream)); } - void bgr_to_bgr565(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr_to_bgr565(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 3); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC2); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 3 ); - cudev::bgr_to_bgr565(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC2); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgr_to_bgr565(src, dst, StreamAccessor::getStream(stream)); } - void rgb_to_bgr555(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void rgb_to_bgr555(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 3); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC2); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 3 ); - cudev::rgb_to_bgr555(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC2); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::rgb_to_bgr555(src, dst, StreamAccessor::getStream(stream)); } - void rgb_to_bgr565(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void rgb_to_bgr565(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 3); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC2); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 3 ); - cudev::rgb_to_bgr565(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC2); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::rgb_to_bgr565(src, dst, StreamAccessor::getStream(stream)); } - void bgra_to_bgr555(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgra_to_bgr555(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 4); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC2); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 4 ); - cudev::bgra_to_bgr555(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC2); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgra_to_bgr555(src, dst, StreamAccessor::getStream(stream)); } - void bgra_to_bgr565(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgra_to_bgr565(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 4); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC2); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 4 ); - cudev::bgra_to_bgr565(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC2); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgra_to_bgr565(src, dst, StreamAccessor::getStream(stream)); } - void rgba_to_bgr555(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void rgba_to_bgr555(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 4); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC2); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 4 ); - cudev::rgba_to_bgr555(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC2); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::rgba_to_bgr555(src, dst, StreamAccessor::getStream(stream)); } - void rgba_to_bgr565(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void rgba_to_bgr565(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 4); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC2); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 4 ); - cudev::rgba_to_bgr565(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC2); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::rgba_to_bgr565(src, dst, StreamAccessor::getStream(stream)); } - void bgr555_to_rgb(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr555_to_rgb(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC3); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 2 ); - cudev::bgr555_to_rgb(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC3); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgr555_to_rgb(src, dst, StreamAccessor::getStream(stream)); } - void bgr565_to_rgb(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr565_to_rgb(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC3); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 2 ); - cudev::bgr565_to_rgb(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC3); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgr565_to_rgb(src, dst, StreamAccessor::getStream(stream)); } - void bgr555_to_bgr(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr555_to_bgr(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC3); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 2 ); - cudev::bgr555_to_bgr(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC3); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgr555_to_bgr(src, dst, StreamAccessor::getStream(stream)); } - void bgr565_to_bgr(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr565_to_bgr(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC3); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 2 ); - cudev::bgr565_to_bgr(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC3); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgr565_to_bgr(src, dst, StreamAccessor::getStream(stream)); } - void bgr555_to_rgba(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr555_to_rgba(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC4); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 2 ); - cudev::bgr555_to_rgba(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC4); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgr555_to_rgba(src, dst, StreamAccessor::getStream(stream)); } - void bgr565_to_rgba(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr565_to_rgba(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC4); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 2 ); - cudev::bgr565_to_rgba(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC4); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgr565_to_rgba(src, dst, StreamAccessor::getStream(stream)); } - void bgr555_to_bgra(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr555_to_bgra(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC4); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 2 ); - cudev::bgr555_to_bgra(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC4); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgr555_to_bgra(src, dst, StreamAccessor::getStream(stream)); } - void bgr565_to_bgra(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr565_to_bgra(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC4); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 2 ); - cudev::bgr565_to_bgra(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC4); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgr565_to_bgra(src, dst, StreamAccessor::getStream(stream)); } - void gray_to_bgr(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void gray_to_bgr(InputArray _src, OutputArray _dst, int, Stream& stream) { using namespace cv::gpu::cudev; 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), 3)); + CV_Assert( src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F ); + CV_Assert( src.channels() == 1 ); + + _dst.create(src.size(), CV_MAKE_TYPE(src.depth(), 3)); + GpuMat dst = _dst.getGpuMat(); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } - void gray_to_bgra(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void gray_to_bgra(InputArray _src, OutputArray _dst, int, Stream& stream) { using namespace cv::gpu::cudev; 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), 4)); + 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)); + GpuMat dst = _dst.getGpuMat(); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } - void gray_to_bgr555(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void gray_to_bgr555(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 1); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC2); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 1 ); - cudev::gray_to_bgr555(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC2); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::gray_to_bgr555(src, dst, StreamAccessor::getStream(stream)); } - void gray_to_bgr565(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void gray_to_bgr565(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 1); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC2); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 1 ); - cudev::gray_to_bgr565(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC2); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::gray_to_bgr565(src, dst, StreamAccessor::getStream(stream)); } - void bgr555_to_gray(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr555_to_gray(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC1); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 2 ); - cudev::bgr555_to_gray(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC1); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgr555_to_gray(src, dst, StreamAccessor::getStream(stream)); } - void bgr565_to_gray(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr565_to_gray(InputArray _src, OutputArray _dst, int, Stream& stream) { - CV_Assert(src.depth() == CV_8U); - CV_Assert(src.channels() == 2); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_8UC1); + CV_Assert( src.depth() == CV_8U ); + CV_Assert( src.channels() == 2 ); - cudev::bgr565_to_gray(src, dst, StreamAccessor::getStream(stream)); + _dst.create(src.size(), CV_8UC1); + GpuMat dst = _dst.getGpuMat(); + + cv::gpu::cudev::bgr565_to_gray(src, dst, StreamAccessor::getStream(stream)); } - void rgb_to_gray(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void rgb_to_gray(InputArray _src, OutputArray _dst, int, Stream& stream) { using namespace cv::gpu::cudev; 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), 1)); + CV_Assert( src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F ); + CV_Assert( src.channels() == 3 ); + + _dst.create(src.size(), CV_MAKE_TYPE(src.depth(), 1)); + GpuMat dst = _dst.getGpuMat(); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } - void bgr_to_gray(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgr_to_gray(InputArray _src, OutputArray _dst, int, Stream& stream) { using namespace cv::gpu::cudev; 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), 1)); + CV_Assert( src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F ); + CV_Assert( src.channels() == 3 ); + + _dst.create(src.size(), CV_MAKE_TYPE(src.depth(), 1)); + GpuMat dst = _dst.getGpuMat(); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } - void rgba_to_gray(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void rgba_to_gray(InputArray _src, OutputArray _dst, int, Stream& stream) { using namespace cv::gpu::cudev; 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), 1)); + CV_Assert( src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F ); + CV_Assert( src.channels() == 4 ); + + _dst.create(src.size(), CV_MAKE_TYPE(src.depth(), 1)); + GpuMat dst = _dst.getGpuMat(); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } - void bgra_to_gray(const GpuMat& src, GpuMat& dst, int, Stream& stream) + void bgra_to_gray(InputArray _src, OutputArray _dst, int, Stream& stream) { using namespace cv::gpu::cudev; 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), 1)); + CV_Assert( src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F ); + CV_Assert( src.channels() == 4 ); + + _dst.create(src.size(), CV_MAKE_TYPE(src.depth(), 1)); + GpuMat dst = _dst.getGpuMat(); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } - void rgb_to_yuv(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream) + void rgb_to_yuv(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -453,16 +550,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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_MAKE_TYPE(src.depth(), dcn)); + GpuMat dst = _dst.getGpuMat(); 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) + void bgr_to_yuv(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -479,16 +579,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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_MAKE_TYPE(src.depth(), dcn)); + GpuMat dst = _dst.getGpuMat(); 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) + void yuv_to_rgb(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -505,16 +608,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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_MAKE_TYPE(src.depth(), dcn)); + GpuMat dst = _dst.getGpuMat(); 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) + void yuv_to_bgr(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -531,16 +637,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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_MAKE_TYPE(src.depth(), dcn)); + GpuMat dst = _dst.getGpuMat(); 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) + void rgb_to_YCrCb(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -557,16 +666,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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_MAKE_TYPE(src.depth(), dcn)); + GpuMat dst = _dst.getGpuMat(); 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) + void bgr_to_YCrCb(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -583,16 +695,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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_MAKE_TYPE(src.depth(), dcn)); + GpuMat dst = _dst.getGpuMat(); 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) + void YCrCb_to_rgb(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -609,16 +724,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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_MAKE_TYPE(src.depth(), dcn)); + GpuMat dst = _dst.getGpuMat(); 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) + void YCrCb_to_bgr(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -635,16 +753,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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_MAKE_TYPE(src.depth(), dcn)); + GpuMat dst = _dst.getGpuMat(); 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) + void rgb_to_xyz(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -661,16 +782,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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_MAKE_TYPE(src.depth(), dcn)); + GpuMat dst = _dst.getGpuMat(); 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) + void bgr_to_xyz(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -687,16 +811,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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_MAKE_TYPE(src.depth(), dcn)); + GpuMat dst = _dst.getGpuMat(); 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) + void xyz_to_rgb(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -713,16 +840,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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_MAKE_TYPE(src.depth(), dcn)); + GpuMat dst = _dst.getGpuMat(); 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) + void xyz_to_bgr(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -739,16 +869,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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_MAKE_TYPE(src.depth(), dcn)); + GpuMat dst = _dst.getGpuMat(); 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) + void rgb_to_hsv(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -765,16 +898,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void bgr_to_hsv(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -791,16 +927,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void hsv_to_rgb(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -817,16 +956,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void hsv_to_bgr(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -843,16 +985,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void rgb_to_hls(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -869,16 +1014,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void bgr_to_hls(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -895,16 +1043,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void hls_to_rgb(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -921,16 +1072,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void hls_to_bgr(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -947,16 +1101,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void rgb_to_hsv_full(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -973,16 +1130,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void bgr_to_hsv_full(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -999,16 +1159,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void hsv_to_rgb_full(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -1025,16 +1188,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void hsv_to_bgr_full(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -1051,16 +1217,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void rgb_to_hls_full(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -1077,16 +1246,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void bgr_to_hls_full(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -1103,16 +1275,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void hls_to_rgb_full(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -1129,16 +1304,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void hls_to_bgr_full(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][6] = @@ -1155,16 +1333,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void bgr_to_lab(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1181,16 +1362,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void rgb_to_lab(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1207,16 +1391,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void lbgr_to_lab(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1233,16 +1420,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void lrgb_to_lab(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1259,16 +1449,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void lab_to_bgr(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1285,16 +1478,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void lab_to_rgb(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1311,16 +1507,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void lab_to_lbgr(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1337,16 +1536,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void lab_to_lrgb(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1363,16 +1565,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void bgr_to_luv(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1389,16 +1594,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void rgb_to_luv(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1415,16 +1623,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void lbgr_to_luv(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1441,16 +1652,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void lrgb_to_luv(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1467,16 +1681,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void luv_to_bgr(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1493,16 +1710,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void luv_to_rgb(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1519,16 +1739,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void luv_to_lbgr(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1545,16 +1768,19 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void luv_to_lrgb(InputArray _src, OutputArray _dst, int dcn, Stream& stream) { using namespace cv::gpu::cudev; static const gpu_func_t funcs[2][2][2] = @@ -1571,28 +1797,34 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKE_TYPE(src.depth(), dcn)); + 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)); + GpuMat dst = _dst.getGpuMat(); 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) + void rgba_to_mbgra(InputArray _src, OutputArray _dst, int, Stream& _stream) { #if (CUDA_VERSION < 5000) - (void)src; - (void)dst; - (void)st; + (void) _src; + (void) _dst; + (void) _stream; CV_Error( Error::StsBadFlag, "Unknown/unsupported color conversion code" ); #else - CV_Assert(src.type() == CV_8UC4 || src.type() == CV_16UC4); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), src.type()); + CV_Assert( src.type() == CV_8UC4 || src.type() == CV_16UC4 ); - cudaStream_t stream = StreamAccessor::getStream(st); + _dst.create(src.size(), src.type()); + GpuMat dst = _dst.getGpuMat(); + + cudaStream_t stream = StreamAccessor::getStream(_stream); NppStreamHandler h(stream); NppiSize oSizeROI; @@ -1609,7 +1841,7 @@ namespace #endif } - void bayer_to_bgr(const GpuMat& src, GpuMat& dst, int dcn, bool blue_last, bool start_with_green, Stream& stream) + void bayer_to_bgr(InputArray _src, OutputArray _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] = @@ -1621,32 +1853,35 @@ namespace 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); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), dcn)); + 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_MAKE_TYPE(src.depth(), dcn)); + GpuMat dst = _dst.getGpuMat(); 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) + void bayerBG_to_bgr(InputArray src, OutputArray 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) + void bayerGB_to_bgr(InputArray src, OutputArray 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) + void bayerRG_to_bgr(InputArray src, OutputArray 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) + void bayerGR_to_bgr(InputArray src, OutputArray dst, int dcn, Stream& stream) { bayer_to_bgr(src, dst, dcn, true, true, stream); } - void bayer_to_gray(const GpuMat& src, GpuMat& dst, bool blue_last, bool start_with_green, Stream& stream) + void bayer_to_gray(InputArray _src, OutputArray _dst, 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] = @@ -1656,26 +1891,29 @@ namespace Bayer2BGR_16u_gpu<1>, }; - CV_Assert(src.type() == CV_8UC1 || src.type() == CV_16UC1); - CV_Assert(src.rows > 2 && src.cols > 2); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), CV_MAKETYPE(src.depth(), 1)); + CV_Assert( src.type() == CV_8UC1 || src.type() == CV_16UC1 ); + CV_Assert( src.rows > 2 && src.cols > 2 ); + + _dst.create(src.size(), CV_MAKE_TYPE(src.depth(), 1)); + GpuMat dst = _dst.getGpuMat(); funcs[src.depth()](src, dst, blue_last, start_with_green, StreamAccessor::getStream(stream)); } - void bayerBG_to_gray(const GpuMat& src, GpuMat& dst, int /*dcn*/, Stream& stream) + void bayerBG_to_gray(InputArray src, OutputArray dst, int /*dcn*/, Stream& stream) { bayer_to_gray(src, dst, false, false, stream); } - void bayerGB_to_gray(const GpuMat& src, GpuMat& dst, int /*dcn*/, Stream& stream) + void bayerGB_to_gray(InputArray src, OutputArray dst, int /*dcn*/, Stream& stream) { bayer_to_gray(src, dst, false, true, stream); } - void bayerRG_to_gray(const GpuMat& src, GpuMat& dst, int /*dcn*/, Stream& stream) + void bayerRG_to_gray(InputArray src, OutputArray dst, int /*dcn*/, Stream& stream) { bayer_to_gray(src, dst, true, false, stream); } - void bayerGR_to_gray(const GpuMat& src, GpuMat& dst, int /*dcn*/, Stream& stream) + void bayerGR_to_gray(InputArray src, OutputArray dst, int /*dcn*/, Stream& stream) { bayer_to_gray(src, dst, true, true, stream); } @@ -1684,9 +1922,9 @@ namespace //////////////////////////////////////////////////////////////////////// // cvtColor -void cv::gpu::cvtColor(const GpuMat& src, GpuMat& dst, int code, int dcn, Stream& stream) +void cv::gpu::cvtColor(InputArray src, OutputArray dst, int code, int dcn, Stream& stream) { - typedef void (*func_t)(const GpuMat& src, GpuMat& dst, int dcn, Stream& stream); + typedef void (*func_t)(InputArray src, OutputArray dst, int dcn, Stream& stream); static const func_t funcs[] = { bgr_to_bgra, // CV_BGR2BGRA =0 @@ -1857,12 +2095,12 @@ void cv::gpu::cvtColor(const GpuMat& src, GpuMat& dst, int code, int dcn, Stream 0, // CV_COLORCVT_MAX = 127 }; - CV_Assert(code < 128); + CV_Assert( code < 128 ); func_t func = funcs[code]; if (func == 0) - CV_Error( cv::Error::StsBadFlag, "Unknown/unsupported color conversion code" ); + CV_Error(Error::StsBadFlag, "Unknown/unsupported color conversion code"); func(src, dst, dcn, stream); } @@ -1870,32 +2108,33 @@ void cv::gpu::cvtColor(const GpuMat& src, GpuMat& dst, int code, int dcn, Stream //////////////////////////////////////////////////////////////////////// // demosaicing -void cv::gpu::demosaicing(const GpuMat& src, GpuMat& dst, int code, int dcn, Stream& stream) +void cv::gpu::demosaicing(InputArray _src, OutputArray _dst, int code, int dcn, Stream& stream) { - const int depth = src.depth(); - - CV_Assert( src.channels() == 1 ); - switch (code) { case cv::COLOR_BayerBG2GRAY: case cv::COLOR_BayerGB2GRAY: case cv::COLOR_BayerRG2GRAY: case cv::COLOR_BayerGR2GRAY: - bayer_to_gray(src, dst, code == cv::COLOR_BayerBG2GRAY || code == cv::COLOR_BayerGB2GRAY, code == cv::COLOR_BayerGB2GRAY || code == cv::COLOR_BayerGR2GRAY, stream); + bayer_to_gray(_src, _dst, code == cv::COLOR_BayerBG2GRAY || code == cv::COLOR_BayerGB2GRAY, code == cv::COLOR_BayerGB2GRAY || code == cv::COLOR_BayerGR2GRAY, stream); break; case cv::COLOR_BayerBG2BGR: case cv::COLOR_BayerGB2BGR: case cv::COLOR_BayerRG2BGR: case cv::COLOR_BayerGR2BGR: - bayer_to_bgr(src, dst, dcn, code == cv::COLOR_BayerBG2BGR || code == cv::COLOR_BayerGB2BGR, code == cv::COLOR_BayerGB2BGR || code == cv::COLOR_BayerGR2BGR, stream); + bayer_to_bgr(_src, _dst, dcn, code == cv::COLOR_BayerBG2BGR || code == cv::COLOR_BayerGB2BGR, code == cv::COLOR_BayerGB2BGR || code == cv::COLOR_BayerGR2BGR, stream); break; case COLOR_BayerBG2BGR_MHT: case COLOR_BayerGB2BGR_MHT: case COLOR_BayerRG2BGR_MHT: case COLOR_BayerGR2BGR_MHT: { - if (dcn <= 0) - dcn = 3; + if (dcn <= 0) dcn = 3; + + GpuMat src = _src.getGpuMat(); + const int depth = _src.depth(); CV_Assert( depth == CV_8U ); + CV_Assert( src.channels() == 1 ); CV_Assert( dcn == 3 || dcn == 4 ); - dst.create(src.size(), CV_MAKETYPE(depth, dcn)); - dst.setTo(Scalar::all(0)); + _dst.create(_src.size(), CV_MAKE_TYPE(depth, dcn)); + GpuMat dst = _dst.getGpuMat(); + + dst.setTo(Scalar::all(0), stream); Size wholeSize; Point ofs; @@ -1906,19 +2145,24 @@ void cv::gpu::demosaicing(const GpuMat& src, GpuMat& dst, int code, int dcn, Str code == COLOR_BayerRG2BGR_MHT || code == COLOR_BayerGR2BGR_MHT ? 0 : 1); if (dcn == 3) - cudev::MHCdemosaic<3>(srcWhole, make_int2(ofs.x, ofs.y), dst, firstRed, StreamAccessor::getStream(stream)); + cv::gpu::cudev::MHCdemosaic<3>(srcWhole, make_int2(ofs.x, ofs.y), dst, firstRed, StreamAccessor::getStream(stream)); else - cudev::MHCdemosaic<4>(srcWhole, make_int2(ofs.x, ofs.y), dst, firstRed, StreamAccessor::getStream(stream)); + cv::gpu::cudev::MHCdemosaic<4>(srcWhole, make_int2(ofs.x, ofs.y), dst, firstRed, StreamAccessor::getStream(stream)); break; } case COLOR_BayerBG2GRAY_MHT: case COLOR_BayerGB2GRAY_MHT: case COLOR_BayerRG2GRAY_MHT: case COLOR_BayerGR2GRAY_MHT: { + GpuMat src = _src.getGpuMat(); + const int depth = _src.depth(); + CV_Assert( depth == CV_8U ); - dst.create(src.size(), CV_MAKETYPE(depth, 1)); - dst.setTo(Scalar::all(0)); + _dst.create(_src.size(), CV_MAKE_TYPE(depth, 1)); + GpuMat dst = _dst.getGpuMat(); + + dst.setTo(Scalar::all(0), stream); Size wholeSize; Point ofs; @@ -1928,25 +2172,26 @@ void cv::gpu::demosaicing(const GpuMat& src, GpuMat& dst, int code, int dcn, Str const int2 firstRed = make_int2(code == COLOR_BayerRG2BGR_MHT || code == COLOR_BayerGB2BGR_MHT ? 0 : 1, code == COLOR_BayerRG2BGR_MHT || code == COLOR_BayerGR2BGR_MHT ? 0 : 1); - cudev::MHCdemosaic<1>(srcWhole, make_int2(ofs.x, ofs.y), dst, firstRed, StreamAccessor::getStream(stream)); + cv::gpu::cudev::MHCdemosaic<1>(srcWhole, make_int2(ofs.x, ofs.y), dst, firstRed, StreamAccessor::getStream(stream)); break; } default: - CV_Error( cv::Error::StsBadFlag, "Unknown / unsupported color conversion code" ); + CV_Error(Error::StsBadFlag, "Unknown / unsupported color conversion code"); } } //////////////////////////////////////////////////////////////////////// // swapChannels -void cv::gpu::swapChannels(GpuMat& image, const int dstOrder[4], Stream& s) +void cv::gpu::swapChannels(InputOutputArray _image, const int dstOrder[4], Stream& _stream) { - CV_Assert(image.type() == CV_8UC4); + GpuMat image = _image.getGpuMat(); - cudaStream_t stream = StreamAccessor::getStream(s); + CV_Assert( image.type() == CV_8UC4 ); + cudaStream_t stream = StreamAccessor::getStream(_stream); NppStreamHandler h(stream); NppiSize sz; @@ -1962,14 +2207,14 @@ void cv::gpu::swapChannels(GpuMat& image, const int dstOrder[4], Stream& s) //////////////////////////////////////////////////////////////////////// // gammaCorrection -void cv::gpu::gammaCorrection(const GpuMat& src, GpuMat& dst, bool forward, Stream& stream) +void cv::gpu::gammaCorrection(InputArray _src, OutputArray _dst, bool forward, Stream& stream) { #if (CUDA_VERSION < 5000) - (void)src; - (void)dst; - (void)forward; - (void)stream; - CV_Error( cv::Error::StsNotImplemented, "This function works only with CUDA 5.0 or higher" ); + (void) _src; + (void) _dst; + (void) forward; + (void) stream; + CV_Error(Error::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); @@ -1985,9 +2230,12 @@ void cv::gpu::gammaCorrection(const GpuMat& src, GpuMat& dst, bool forward, Stre {0, 0, 0, nppiGammaFwd_8u_C3IR, nppiGammaFwd_8u_AC4IR} }; - CV_Assert(src.type() == CV_8UC3 || src.type() == CV_8UC4); + GpuMat src = _src.getGpuMat(); - dst.create(src.size(), src.type()); + CV_Assert( src.type() == CV_8UC3 || src.type() == CV_8UC4 ); + + _dst.create(src.size(), src.type()); + GpuMat dst = _dst.getGpuMat(); NppStreamHandler h(StreamAccessor::getStream(stream)); @@ -2036,7 +2284,7 @@ namespace }; } -void cv::gpu::alphaComp(const GpuMat& img1, const GpuMat& img2, GpuMat& dst, int alpha_op, Stream& stream) +void cv::gpu::alphaComp(InputArray _img1, InputArray _img2, OutputArray _dst, int alpha_op, Stream& stream) { static const NppiAlphaOp npp_alpha_ops[] = { NPPI_OP_ALPHA_OVER, @@ -2055,7 +2303,6 @@ void cv::gpu::alphaComp(const GpuMat& img1, const GpuMat& img2, GpuMat& dst, int }; typedef void (*func_t)(const GpuMat& img1, const GpuMat& img2, GpuMat& dst, NppiAlphaOp eAlphaOp, cudaStream_t stream); - static const func_t funcs[] = { NppAlphaComp::call, @@ -2066,10 +2313,14 @@ void cv::gpu::alphaComp(const GpuMat& img1, const GpuMat& img2, GpuMat& dst, int NppAlphaComp::call }; + GpuMat img1 = _img1.getGpuMat(); + GpuMat img2 = _img2.getGpuMat(); + CV_Assert( img1.type() == CV_8UC4 || img1.type() == CV_16UC4 || img1.type() == CV_32SC4 || img1.type() == CV_32FC4 ); CV_Assert( img1.size() == img2.size() && img1.type() == img2.type() ); - dst.create(img1.size(), img1.type()); + _dst.create(img1.size(), img1.type()); + GpuMat dst = _dst.getGpuMat(); const func_t func = funcs[img1.depth()]; diff --git a/modules/gpuimgproc/src/corners.cpp b/modules/gpuimgproc/src/corners.cpp index 824a3308e..6b53e6f85 100644 --- a/modules/gpuimgproc/src/corners.cpp +++ b/modules/gpuimgproc/src/corners.cpp @@ -45,15 +45,10 @@ using namespace cv; using namespace cv::gpu; -#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) +#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) || !defined(HAVE_OPENCV_GPUFILTERS) -void cv::gpu::cornerHarris(const GpuMat&, GpuMat&, int, int, double, int) { throw_no_cuda(); } -void cv::gpu::cornerHarris(const GpuMat&, GpuMat&, GpuMat&, GpuMat&, int, int, double, int) { throw_no_cuda(); } -void cv::gpu::cornerHarris(const GpuMat&, GpuMat&, GpuMat&, GpuMat&, GpuMat&, int, int, double, int, Stream&) { throw_no_cuda(); } - -void cv::gpu::cornerMinEigenVal(const GpuMat&, GpuMat&, int, int, int) { throw_no_cuda(); } -void cv::gpu::cornerMinEigenVal(const GpuMat&, GpuMat&, GpuMat&, GpuMat&, int, int, int) { throw_no_cuda(); } -void cv::gpu::cornerMinEigenVal(const GpuMat&, GpuMat&, GpuMat&, GpuMat&, GpuMat&, int, int, int, Stream&) { throw_no_cuda(); } +Ptr cv::gpu::createHarrisCorner(int, int, int, double, int) { throw_no_cuda(); return Ptr(); } +Ptr cv::gpu::createMinEigenValCorner(int, int, int, int) { throw_no_cuda(); return Ptr(); } #else /* !defined (HAVE_CUDA) */ @@ -68,89 +63,127 @@ namespace cv { namespace gpu { namespace cudev namespace { - void extractCovData(const GpuMat& src, GpuMat& Dx, GpuMat& Dy, GpuMat& buf, int blockSize, int ksize, int borderType, Stream& stream) + class CornerBase : public CornernessCriteria { - (void) buf; + protected: + CornerBase(int srcType, int blockSize, int ksize, int borderType); - double scale = static_cast(1 << ((ksize > 0 ? ksize : 3) - 1)) * blockSize; + void extractCovData(const GpuMat& src, Stream& stream); - if (ksize < 0) + int srcType_; + int blockSize_; + int ksize_; + int borderType_; + GpuMat Dx_, Dy_; + + private: + Ptr filterDx_, filterDy_; + }; + + CornerBase::CornerBase(int srcType, int blockSize, int ksize, int borderType) : + srcType_(srcType), blockSize_(blockSize), ksize_(ksize), borderType_(borderType) + { + CV_Assert( borderType_ == BORDER_REFLECT101 || borderType_ == BORDER_REPLICATE || borderType_ == BORDER_REFLECT ); + + const int sdepth = CV_MAT_DEPTH(srcType_); + const int cn = CV_MAT_CN(srcType_); + + CV_Assert( cn == 1 ); + + double scale = static_cast(1 << ((ksize_ > 0 ? ksize_ : 3) - 1)) * blockSize_; + + if (ksize_ < 0) scale *= 2.; - if (src.depth() == CV_8U) + if (sdepth == CV_8U) scale *= 255.; scale = 1./scale; - Dx.create(src.size(), CV_32F); - Dy.create(src.size(), CV_32F); - - Ptr filterDx, filterDy; - - if (ksize > 0) + if (ksize_ > 0) { - filterDx = gpu::createSobelFilter(src.type(), CV_32F, 1, 0, ksize, scale, borderType); - filterDy = gpu::createSobelFilter(src.type(), CV_32F, 0, 1, ksize, scale, borderType); + filterDx_ = gpu::createSobelFilter(srcType, CV_32F, 1, 0, ksize_, scale, borderType_); + filterDy_ = gpu::createSobelFilter(srcType, CV_32F, 0, 1, ksize_, scale, borderType_); } else { - filterDx = gpu::createScharrFilter(src.type(), CV_32F, 1, 0, scale, borderType); - filterDy = gpu::createScharrFilter(src.type(), CV_32F, 0, 1, scale, borderType); + filterDx_ = gpu::createScharrFilter(srcType, CV_32F, 1, 0, scale, borderType_); + filterDy_ = gpu::createScharrFilter(srcType, CV_32F, 0, 1, scale, borderType_); + } + } + + void CornerBase::extractCovData(const GpuMat& src, Stream& stream) + { + CV_Assert( src.type() == srcType_ ); + filterDx_->apply(src, Dx_, stream); + filterDy_->apply(src, Dy_, stream); + } + + class Harris : public CornerBase + { + public: + Harris(int srcType, int blockSize, int ksize, double k, int borderType) : + CornerBase(srcType, blockSize, ksize, borderType), k_(static_cast(k)) + { } - filterDx->apply(src, Dx); - filterDy->apply(src, Dy); + void compute(InputArray src, OutputArray dst, Stream& stream = Stream::Null()); + + private: + float k_; + }; + + void Harris::compute(InputArray _src, OutputArray _dst, Stream& stream) + { + using namespace cv::gpu::cudev::imgproc; + + GpuMat src = _src.getGpuMat(); + + extractCovData(src, stream); + + _dst.create(src.size(), CV_32FC1); + GpuMat dst = _dst.getGpuMat(); + + cornerHarris_gpu(blockSize_, k_, Dx_, Dy_, dst, borderType_, StreamAccessor::getStream(stream)); + } + + class MinEigenVal : public CornerBase + { + public: + MinEigenVal(int srcType, int blockSize, int ksize, int borderType) : + CornerBase(srcType, blockSize, ksize, borderType) + { + } + + void compute(InputArray src, OutputArray dst, Stream& stream = Stream::Null()); + + private: + float k_; + }; + + void MinEigenVal::compute(InputArray _src, OutputArray _dst, Stream& stream) + { + using namespace cv::gpu::cudev::imgproc; + + GpuMat src = _src.getGpuMat(); + + extractCovData(src, stream); + + _dst.create(src.size(), CV_32FC1); + GpuMat dst = _dst.getGpuMat(); + + cornerMinEigenVal_gpu(blockSize_, Dx_, Dy_, dst, borderType_, StreamAccessor::getStream(stream)); } } -void cv::gpu::cornerHarris(const GpuMat& src, GpuMat& dst, int blockSize, int ksize, double k, int borderType) +Ptr cv::gpu::createHarrisCorner(int srcType, int blockSize, int ksize, double k, int borderType) { - GpuMat Dx, Dy; - cornerHarris(src, dst, Dx, Dy, blockSize, ksize, k, borderType); + return makePtr(srcType, blockSize, ksize, k, borderType); } -void cv::gpu::cornerHarris(const GpuMat& src, GpuMat& dst, GpuMat& Dx, GpuMat& Dy, int blockSize, int ksize, double k, int borderType) +Ptr cv::gpu::createMinEigenValCorner(int srcType, int blockSize, int ksize, int borderType) { - GpuMat buf; - cornerHarris(src, dst, Dx, Dy, buf, blockSize, ksize, k, borderType); -} - -void cv::gpu::cornerHarris(const GpuMat& src, GpuMat& dst, GpuMat& Dx, GpuMat& Dy, GpuMat& buf, int blockSize, int ksize, double k, int borderType, Stream& stream) -{ - using namespace cv::gpu::cudev::imgproc; - - CV_Assert(borderType == cv::BORDER_REFLECT101 || borderType == cv::BORDER_REPLICATE || borderType == cv::BORDER_REFLECT); - - extractCovData(src, Dx, Dy, buf, blockSize, ksize, borderType, stream); - - dst.create(src.size(), CV_32F); - - cornerHarris_gpu(blockSize, static_cast(k), Dx, Dy, dst, borderType, StreamAccessor::getStream(stream)); -} - -void cv::gpu::cornerMinEigenVal(const GpuMat& src, GpuMat& dst, int blockSize, int ksize, int borderType) -{ - GpuMat Dx, Dy; - cornerMinEigenVal(src, dst, Dx, Dy, blockSize, ksize, borderType); -} - -void cv::gpu::cornerMinEigenVal(const GpuMat& src, GpuMat& dst, GpuMat& Dx, GpuMat& Dy, int blockSize, int ksize, int borderType) -{ - GpuMat buf; - cornerMinEigenVal(src, dst, Dx, Dy, buf, blockSize, ksize, borderType); -} - -void cv::gpu::cornerMinEigenVal(const GpuMat& src, GpuMat& dst, GpuMat& Dx, GpuMat& Dy, GpuMat& buf, int blockSize, int ksize, int borderType, Stream& stream) -{ - using namespace ::cv::gpu::cudev::imgproc; - - CV_Assert(borderType == cv::BORDER_REFLECT101 || borderType == cv::BORDER_REPLICATE || borderType == cv::BORDER_REFLECT); - - extractCovData(src, Dx, Dy, buf, blockSize, ksize, borderType, stream); - - dst.create(src.size(), CV_32F); - - cornerMinEigenVal_gpu(blockSize, Dx, Dy, dst, borderType, StreamAccessor::getStream(stream)); + return makePtr(srcType, blockSize, ksize, borderType); } #endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpuimgproc/src/cuda/bilateral_filter.cu b/modules/gpuimgproc/src/cuda/bilateral_filter.cu index 6aa5df27a..3192f649b 100644 --- a/modules/gpuimgproc/src/cuda/bilateral_filter.cu +++ b/modules/gpuimgproc/src/cuda/bilateral_filter.cu @@ -133,7 +133,7 @@ namespace cv { namespace gpu { namespace cudev B b(src.rows, src.cols); float sigma_spatial2_inv_half = -0.5f/(sigma_spatial * sigma_spatial); - float sigma_color2_inv_half = -0.5f/(sigma_color * sigma_color); + float sigma_color2_inv_half = -0.5f/(sigma_color * sigma_color); cudaSafeCall( cudaFuncSetCacheConfig (bilateral_kernel >, cudaFuncCachePreferL1) ); bilateral_kernel<<>>((PtrStepSz)src, (PtrStepSz)dst, b, kernel_size, sigma_spatial2_inv_half, sigma_color2_inv_half); diff --git a/modules/gpuimgproc/src/cuda/build_point_list.cu b/modules/gpuimgproc/src/cuda/build_point_list.cu new file mode 100644 index 000000000..c5f2b23f6 --- /dev/null +++ b/modules/gpuimgproc/src/cuda/build_point_list.cu @@ -0,0 +1,138 @@ +/*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/core/cuda/common.hpp" +#include "opencv2/core/cuda/emulation.hpp" + +namespace cv { namespace gpu { namespace cudev +{ + namespace hough + { + __device__ int g_counter; + + template + __global__ void buildPointList(const PtrStepSzb src, unsigned int* list) + { + __shared__ unsigned int s_queues[4][32 * PIXELS_PER_THREAD]; + __shared__ int s_qsize[4]; + __shared__ int s_globStart[4]; + + const int x = blockIdx.x * blockDim.x * PIXELS_PER_THREAD + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (threadIdx.x == 0) + s_qsize[threadIdx.y] = 0; + __syncthreads(); + + if (y < src.rows) + { + // fill the queue + const uchar* srcRow = src.ptr(y); + for (int i = 0, xx = x; i < PIXELS_PER_THREAD && xx < src.cols; ++i, xx += blockDim.x) + { + if (srcRow[xx]) + { + const unsigned int val = (y << 16) | xx; + const int qidx = Emulation::smem::atomicAdd(&s_qsize[threadIdx.y], 1); + s_queues[threadIdx.y][qidx] = val; + } + } + } + + __syncthreads(); + + // let one thread reserve the space required in the global list + if (threadIdx.x == 0 && threadIdx.y == 0) + { + // find how many items are stored in each list + int totalSize = 0; + for (int i = 0; i < blockDim.y; ++i) + { + s_globStart[i] = totalSize; + totalSize += s_qsize[i]; + } + + // calculate the offset in the global list + const int globalOffset = atomicAdd(&g_counter, totalSize); + for (int i = 0; i < blockDim.y; ++i) + s_globStart[i] += globalOffset; + } + + __syncthreads(); + + // copy local queues to global queue + const int qsize = s_qsize[threadIdx.y]; + int gidx = s_globStart[threadIdx.y] + threadIdx.x; + for(int i = threadIdx.x; i < qsize; i += blockDim.x, gidx += blockDim.x) + list[gidx] = s_queues[threadIdx.y][i]; + } + + int buildPointList_gpu(PtrStepSzb src, unsigned int* list) + { + const int PIXELS_PER_THREAD = 16; + + void* counterPtr; + cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); + + cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); + + const dim3 block(32, 4); + const dim3 grid(divUp(src.cols, block.x * PIXELS_PER_THREAD), divUp(src.rows, block.y)); + + cudaSafeCall( cudaFuncSetCacheConfig(buildPointList, cudaFuncCachePreferShared) ); + + buildPointList<<>>(src, list); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + int totalCount; + cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); + + return totalCount; + } + } +}}} + +#endif /* CUDA_DISABLER */ diff --git a/modules/gpuimgproc/src/cuda/canny.cu b/modules/gpuimgproc/src/cuda/canny.cu index 177d14692..271fffbc7 100644 --- a/modules/gpuimgproc/src/cuda/canny.cu +++ b/modules/gpuimgproc/src/cuda/canny.cu @@ -43,7 +43,7 @@ #if !defined CUDA_DISABLER #include -#include //std::swap +#include #include "opencv2/core/cuda/common.hpp" #include "opencv2/core/cuda/emulation.hpp" #include "opencv2/core/cuda/transform.hpp" diff --git a/modules/gpuimgproc/src/cuda/corners.cu b/modules/gpuimgproc/src/cuda/corners.cu index 39e7cdc5d..aa65ac8f8 100644 --- a/modules/gpuimgproc/src/cuda/corners.cu +++ b/modules/gpuimgproc/src/cuda/corners.cu @@ -48,6 +48,10 @@ #include "opencv2/core/cuda/saturate_cast.hpp" #include "opencv2/core/cuda/border_interpolate.hpp" +#include "opencv2/opencv_modules.hpp" + +#ifdef HAVE_OPENCV_GPUFILTERS + namespace cv { namespace gpu { namespace cudev { namespace imgproc @@ -271,4 +275,6 @@ namespace cv { namespace gpu { namespace cudev } }}} -#endif +#endif // HAVE_OPENCV_GPUFILTERS + +#endif // CUDA_DISABLER diff --git a/modules/gpuimgproc/src/cuda/generalized_hough.cu b/modules/gpuimgproc/src/cuda/generalized_hough.cu new file mode 100644 index 000000000..fdf691ff4 --- /dev/null +++ b/modules/gpuimgproc/src/cuda/generalized_hough.cu @@ -0,0 +1,824 @@ +/*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 "opencv2/core/cuda/common.hpp" +#include "opencv2/core/cuda/emulation.hpp" +#include "opencv2/core/cuda/vec_math.hpp" +#include "opencv2/core/cuda/functional.hpp" + +#include "opencv2/opencv_modules.hpp" + +#ifdef HAVE_OPENCV_GPUARITHM + +namespace cv { namespace gpu { namespace cudev +{ + namespace ght + { + __device__ int g_counter; + + template + __global__ void buildEdgePointList(const PtrStepSzb edges, const PtrStep dx, const PtrStep dy, + unsigned int* coordList, float* thetaList) + { + __shared__ unsigned int s_coordLists[4][32 * PIXELS_PER_THREAD]; + __shared__ float s_thetaLists[4][32 * PIXELS_PER_THREAD]; + __shared__ int s_sizes[4]; + __shared__ int s_globStart[4]; + + const int x = blockIdx.x * blockDim.x * PIXELS_PER_THREAD + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (threadIdx.x == 0) + s_sizes[threadIdx.y] = 0; + __syncthreads(); + + if (y < edges.rows) + { + // fill the queue + const uchar* edgesRow = edges.ptr(y); + const T* dxRow = dx.ptr(y); + const T* dyRow = dy.ptr(y); + + for (int i = 0, xx = x; i < PIXELS_PER_THREAD && xx < edges.cols; ++i, xx += blockDim.x) + { + const T dxVal = dxRow[xx]; + const T dyVal = dyRow[xx]; + + if (edgesRow[xx] && (dxVal != 0 || dyVal != 0)) + { + const unsigned int coord = (y << 16) | xx; + + float theta = ::atan2f(dyVal, dxVal); + if (theta < 0) + theta += 2.0f * CV_PI_F; + + const int qidx = Emulation::smem::atomicAdd(&s_sizes[threadIdx.y], 1); + + s_coordLists[threadIdx.y][qidx] = coord; + s_thetaLists[threadIdx.y][qidx] = theta; + } + } + } + + __syncthreads(); + + // let one thread reserve the space required in the global list + if (threadIdx.x == 0 && threadIdx.y == 0) + { + // find how many items are stored in each list + int totalSize = 0; + for (int i = 0; i < blockDim.y; ++i) + { + s_globStart[i] = totalSize; + totalSize += s_sizes[i]; + } + + // calculate the offset in the global list + const int globalOffset = atomicAdd(&g_counter, totalSize); + for (int i = 0; i < blockDim.y; ++i) + s_globStart[i] += globalOffset; + } + + __syncthreads(); + + // copy local queues to global queue + const int qsize = s_sizes[threadIdx.y]; + int gidx = s_globStart[threadIdx.y] + threadIdx.x; + for(int i = threadIdx.x; i < qsize; i += blockDim.x, gidx += blockDim.x) + { + coordList[gidx] = s_coordLists[threadIdx.y][i]; + thetaList[gidx] = s_thetaLists[threadIdx.y][i]; + } + } + + template + int buildEdgePointList_gpu(PtrStepSzb edges, PtrStepSzb dx, PtrStepSzb dy, unsigned int* coordList, float* thetaList) + { + const int PIXELS_PER_THREAD = 8; + + void* counterPtr; + cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); + + cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); + + const dim3 block(32, 4); + const dim3 grid(divUp(edges.cols, block.x * PIXELS_PER_THREAD), divUp(edges.rows, block.y)); + + cudaSafeCall( cudaFuncSetCacheConfig(buildEdgePointList, cudaFuncCachePreferShared) ); + + buildEdgePointList<<>>(edges, (PtrStepSz) dx, (PtrStepSz) dy, coordList, thetaList); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + int totalCount; + cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); + + return totalCount; + } + + template int buildEdgePointList_gpu(PtrStepSzb edges, PtrStepSzb dx, PtrStepSzb dy, unsigned int* coordList, float* thetaList); + template int buildEdgePointList_gpu(PtrStepSzb edges, PtrStepSzb dx, PtrStepSzb dy, unsigned int* coordList, float* thetaList); + template int buildEdgePointList_gpu(PtrStepSzb edges, PtrStepSzb dx, PtrStepSzb dy, unsigned int* coordList, float* thetaList); + + __global__ void buildRTable(const unsigned int* coordList, const float* thetaList, const int pointsCount, + PtrStep r_table, int* r_sizes, int maxSize, + const short2 templCenter, const float thetaScale) + { + const int tid = blockIdx.x * blockDim.x + threadIdx.x; + + if (tid >= pointsCount) + return; + + const unsigned int coord = coordList[tid]; + short2 p; + p.x = (coord & 0xFFFF); + p.y = (coord >> 16) & 0xFFFF; + + const float theta = thetaList[tid]; + const int n = __float2int_rn(theta * thetaScale); + + const int ind = ::atomicAdd(r_sizes + n, 1); + if (ind < maxSize) + r_table(n, ind) = saturate_cast(p - templCenter); + } + + void buildRTable_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, + PtrStepSz r_table, int* r_sizes, + short2 templCenter, int levels) + { + const dim3 block(256); + const dim3 grid(divUp(pointsCount, block.x)); + + const float thetaScale = levels / (2.0f * CV_PI_F); + + buildRTable<<>>(coordList, thetaList, pointsCount, r_table, r_sizes, r_table.cols, templCenter, thetaScale); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + } + + //////////////////////////////////////////////////////////////////////// + // Ballard_Pos + + __global__ void Ballard_Pos_calcHist(const unsigned int* coordList, const float* thetaList, const int pointsCount, + const PtrStep r_table, const int* r_sizes, + PtrStepSzi hist, + const float idp, const float thetaScale) + { + const int tid = blockIdx.x * blockDim.x + threadIdx.x; + + if (tid >= pointsCount) + return; + + const unsigned int coord = coordList[tid]; + short2 p; + p.x = (coord & 0xFFFF); + p.y = (coord >> 16) & 0xFFFF; + + const float theta = thetaList[tid]; + const int n = __float2int_rn(theta * thetaScale); + + const short2* r_row = r_table.ptr(n); + const int r_row_size = r_sizes[n]; + + for (int j = 0; j < r_row_size; ++j) + { + short2 c = saturate_cast(p - r_row[j]); + + c.x = __float2int_rn(c.x * idp); + c.y = __float2int_rn(c.y * idp); + + if (c.x >= 0 && c.x < hist.cols - 2 && c.y >= 0 && c.y < hist.rows - 2) + ::atomicAdd(hist.ptr(c.y + 1) + c.x + 1, 1); + } + } + + void Ballard_Pos_calcHist_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, + PtrStepSz r_table, const int* r_sizes, + PtrStepSzi hist, + float dp, int levels) + { + const dim3 block(256); + const dim3 grid(divUp(pointsCount, block.x)); + + const float idp = 1.0f / dp; + const float thetaScale = levels / (2.0f * CV_PI_F); + + Ballard_Pos_calcHist<<>>(coordList, thetaList, pointsCount, r_table, r_sizes, hist, idp, thetaScale); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + } + + __global__ void Ballard_Pos_findPosInHist(const PtrStepSzi hist, float4* out, int3* votes, + const int maxSize, const float dp, const int threshold) + { + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= hist.cols - 2 || y >= hist.rows - 2) + return; + + const int curVotes = hist(y + 1, x + 1); + + if (curVotes > threshold && + curVotes > hist(y + 1, x) && + curVotes >= hist(y + 1, x + 2) && + curVotes > hist(y, x + 1) && + curVotes >= hist(y + 2, x + 1)) + { + const int ind = ::atomicAdd(&g_counter, 1); + + if (ind < maxSize) + { + out[ind] = make_float4(x * dp, y * dp, 1.0f, 0.0f); + votes[ind] = make_int3(curVotes, 0, 0); + } + } + } + + int Ballard_Pos_findPosInHist_gpu(PtrStepSzi hist, float4* out, int3* votes, int maxSize, float dp, int threshold) + { + void* counterPtr; + cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); + + cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); + + const dim3 block(32, 8); + const dim3 grid(divUp(hist.cols - 2, block.x), divUp(hist.rows - 2, block.y)); + + cudaSafeCall( cudaFuncSetCacheConfig(Ballard_Pos_findPosInHist, cudaFuncCachePreferL1) ); + + Ballard_Pos_findPosInHist<<>>(hist, out, votes, maxSize, dp, threshold); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + int totalCount; + cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); + + totalCount = ::min(totalCount, maxSize); + + return totalCount; + } + + //////////////////////////////////////////////////////////////////////// + // Guil_Full + + struct FeatureTable + { + uchar* p1_pos_data; + size_t p1_pos_step; + + uchar* p1_theta_data; + size_t p1_theta_step; + + uchar* p2_pos_data; + size_t p2_pos_step; + + uchar* d12_data; + size_t d12_step; + + uchar* r1_data; + size_t r1_step; + + uchar* r2_data; + size_t r2_step; + }; + + __constant__ FeatureTable c_templFeatures; + __constant__ FeatureTable c_imageFeatures; + + void Guil_Full_setTemplFeatures(PtrStepb p1_pos, PtrStepb p1_theta, PtrStepb p2_pos, PtrStepb d12, PtrStepb r1, PtrStepb r2) + { + FeatureTable tbl; + + tbl.p1_pos_data = p1_pos.data; + tbl.p1_pos_step = p1_pos.step; + + tbl.p1_theta_data = p1_theta.data; + tbl.p1_theta_step = p1_theta.step; + + tbl.p2_pos_data = p2_pos.data; + tbl.p2_pos_step = p2_pos.step; + + tbl.d12_data = d12.data; + tbl.d12_step = d12.step; + + tbl.r1_data = r1.data; + tbl.r1_step = r1.step; + + tbl.r2_data = r2.data; + tbl.r2_step = r2.step; + + cudaSafeCall( cudaMemcpyToSymbol(c_templFeatures, &tbl, sizeof(FeatureTable)) ); + } + void Guil_Full_setImageFeatures(PtrStepb p1_pos, PtrStepb p1_theta, PtrStepb p2_pos, PtrStepb d12, PtrStepb r1, PtrStepb r2) + { + FeatureTable tbl; + + tbl.p1_pos_data = p1_pos.data; + tbl.p1_pos_step = p1_pos.step; + + tbl.p1_theta_data = p1_theta.data; + tbl.p1_theta_step = p1_theta.step; + + tbl.p2_pos_data = p2_pos.data; + tbl.p2_pos_step = p2_pos.step; + + tbl.d12_data = d12.data; + tbl.d12_step = d12.step; + + tbl.r1_data = r1.data; + tbl.r1_step = r1.step; + + tbl.r2_data = r2.data; + tbl.r2_step = r2.step; + + cudaSafeCall( cudaMemcpyToSymbol(c_imageFeatures, &tbl, sizeof(FeatureTable)) ); + } + + struct TemplFeatureTable + { + static __device__ float2* p1_pos(int n) + { + return (float2*)(c_templFeatures.p1_pos_data + n * c_templFeatures.p1_pos_step); + } + static __device__ float* p1_theta(int n) + { + return (float*)(c_templFeatures.p1_theta_data + n * c_templFeatures.p1_theta_step); + } + static __device__ float2* p2_pos(int n) + { + return (float2*)(c_templFeatures.p2_pos_data + n * c_templFeatures.p2_pos_step); + } + + static __device__ float* d12(int n) + { + return (float*)(c_templFeatures.d12_data + n * c_templFeatures.d12_step); + } + + static __device__ float2* r1(int n) + { + return (float2*)(c_templFeatures.r1_data + n * c_templFeatures.r1_step); + } + static __device__ float2* r2(int n) + { + return (float2*)(c_templFeatures.r2_data + n * c_templFeatures.r2_step); + } + }; + struct ImageFeatureTable + { + static __device__ float2* p1_pos(int n) + { + return (float2*)(c_imageFeatures.p1_pos_data + n * c_imageFeatures.p1_pos_step); + } + static __device__ float* p1_theta(int n) + { + return (float*)(c_imageFeatures.p1_theta_data + n * c_imageFeatures.p1_theta_step); + } + static __device__ float2* p2_pos(int n) + { + return (float2*)(c_imageFeatures.p2_pos_data + n * c_imageFeatures.p2_pos_step); + } + + static __device__ float* d12(int n) + { + return (float*)(c_imageFeatures.d12_data + n * c_imageFeatures.d12_step); + } + + static __device__ float2* r1(int n) + { + return (float2*)(c_imageFeatures.r1_data + n * c_imageFeatures.r1_step); + } + static __device__ float2* r2(int n) + { + return (float2*)(c_imageFeatures.r2_data + n * c_imageFeatures.r2_step); + } + }; + + __device__ float clampAngle(float a) + { + float res = a; + + while (res > 2.0f * CV_PI_F) + res -= 2.0f * CV_PI_F; + while (res < 0.0f) + res += 2.0f * CV_PI_F; + + return res; + } + + __device__ bool angleEq(float a, float b, float eps) + { + return (::fabs(clampAngle(a - b)) <= eps); + } + + template + __global__ void Guil_Full_buildFeatureList(const unsigned int* coordList, const float* thetaList, const int pointsCount, + int* sizes, const int maxSize, + const float xi, const float angleEpsilon, const float alphaScale, + const float2 center, const float maxDist) + { + const float p1_theta = thetaList[blockIdx.x]; + const unsigned int coord1 = coordList[blockIdx.x]; + float2 p1_pos; + p1_pos.x = (coord1 & 0xFFFF); + p1_pos.y = (coord1 >> 16) & 0xFFFF; + + for (int i = threadIdx.x; i < pointsCount; i += blockDim.x) + { + const float p2_theta = thetaList[i]; + const unsigned int coord2 = coordList[i]; + float2 p2_pos; + p2_pos.x = (coord2 & 0xFFFF); + p2_pos.y = (coord2 >> 16) & 0xFFFF; + + if (angleEq(p1_theta - p2_theta, xi, angleEpsilon)) + { + const float2 d = p1_pos - p2_pos; + + float alpha12 = clampAngle(::atan2(d.y, d.x) - p1_theta); + float d12 = ::sqrtf(d.x * d.x + d.y * d.y); + + if (d12 > maxDist) + continue; + + float2 r1 = p1_pos - center; + float2 r2 = p2_pos - center; + + const int n = __float2int_rn(alpha12 * alphaScale); + + const int ind = ::atomicAdd(sizes + n, 1); + + if (ind < maxSize) + { + if (!isTempl) + { + FT::p1_pos(n)[ind] = p1_pos; + FT::p2_pos(n)[ind] = p2_pos; + } + + FT::p1_theta(n)[ind] = p1_theta; + + FT::d12(n)[ind] = d12; + + if (isTempl) + { + FT::r1(n)[ind] = r1; + FT::r2(n)[ind] = r2; + } + } + } + } + } + + template + void Guil_Full_buildFeatureList_caller(const unsigned int* coordList, const float* thetaList, int pointsCount, + int* sizes, int maxSize, + float xi, float angleEpsilon, int levels, + float2 center, float maxDist) + { + const dim3 block(256); + const dim3 grid(pointsCount); + + const float alphaScale = levels / (2.0f * CV_PI_F); + + Guil_Full_buildFeatureList<<>>(coordList, thetaList, pointsCount, + sizes, maxSize, + xi * (CV_PI_F / 180.0f), angleEpsilon * (CV_PI_F / 180.0f), alphaScale, + center, maxDist); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + thrust::device_ptr sizesPtr(sizes); + thrust::transform(sizesPtr, sizesPtr + levels + 1, sizesPtr, cudev::bind2nd(cudev::minimum(), maxSize)); + } + + void Guil_Full_buildTemplFeatureList_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, + int* sizes, int maxSize, + float xi, float angleEpsilon, int levels, + float2 center, float maxDist) + { + Guil_Full_buildFeatureList_caller(coordList, thetaList, pointsCount, + sizes, maxSize, + xi, angleEpsilon, levels, + center, maxDist); + } + void Guil_Full_buildImageFeatureList_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, + int* sizes, int maxSize, + float xi, float angleEpsilon, int levels, + float2 center, float maxDist) + { + Guil_Full_buildFeatureList_caller(coordList, thetaList, pointsCount, + sizes, maxSize, + xi, angleEpsilon, levels, + center, maxDist); + } + + __global__ void Guil_Full_calcOHist(const int* templSizes, const int* imageSizes, int* OHist, + const float minAngle, const float maxAngle, const float iAngleStep, const int angleRange) + { + extern __shared__ int s_OHist[]; + for (int i = threadIdx.x; i <= angleRange; i += blockDim.x) + s_OHist[i] = 0; + __syncthreads(); + + const int tIdx = blockIdx.x; + const int level = blockIdx.y; + + const int tSize = templSizes[level]; + + if (tIdx < tSize) + { + const int imSize = imageSizes[level]; + + const float t_p1_theta = TemplFeatureTable::p1_theta(level)[tIdx]; + + for (int i = threadIdx.x; i < imSize; i += blockDim.x) + { + const float im_p1_theta = ImageFeatureTable::p1_theta(level)[i]; + + const float angle = clampAngle(im_p1_theta - t_p1_theta); + + if (angle >= minAngle && angle <= maxAngle) + { + const int n = __float2int_rn((angle - minAngle) * iAngleStep); + Emulation::smem::atomicAdd(&s_OHist[n], 1); + } + } + } + __syncthreads(); + + for (int i = threadIdx.x; i <= angleRange; i += blockDim.x) + ::atomicAdd(OHist + i, s_OHist[i]); + } + + void Guil_Full_calcOHist_gpu(const int* templSizes, const int* imageSizes, int* OHist, + float minAngle, float maxAngle, float angleStep, int angleRange, + int levels, int tMaxSize) + { + const dim3 block(256); + const dim3 grid(tMaxSize, levels + 1); + + minAngle *= (CV_PI_F / 180.0f); + maxAngle *= (CV_PI_F / 180.0f); + angleStep *= (CV_PI_F / 180.0f); + + const size_t smemSize = (angleRange + 1) * sizeof(float); + + Guil_Full_calcOHist<<>>(templSizes, imageSizes, OHist, + minAngle, maxAngle, 1.0f / angleStep, angleRange); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + } + + __global__ void Guil_Full_calcSHist(const int* templSizes, const int* imageSizes, int* SHist, + const float angle, const float angleEpsilon, + const float minScale, const float maxScale, const float iScaleStep, const int scaleRange) + { + extern __shared__ int s_SHist[]; + for (int i = threadIdx.x; i <= scaleRange; i += blockDim.x) + s_SHist[i] = 0; + __syncthreads(); + + const int tIdx = blockIdx.x; + const int level = blockIdx.y; + + const int tSize = templSizes[level]; + + if (tIdx < tSize) + { + const int imSize = imageSizes[level]; + + const float t_p1_theta = TemplFeatureTable::p1_theta(level)[tIdx] + angle; + const float t_d12 = TemplFeatureTable::d12(level)[tIdx] + angle; + + for (int i = threadIdx.x; i < imSize; i += blockDim.x) + { + const float im_p1_theta = ImageFeatureTable::p1_theta(level)[i]; + const float im_d12 = ImageFeatureTable::d12(level)[i]; + + if (angleEq(im_p1_theta, t_p1_theta, angleEpsilon)) + { + const float scale = im_d12 / t_d12; + + if (scale >= minScale && scale <= maxScale) + { + const int s = __float2int_rn((scale - minScale) * iScaleStep); + Emulation::smem::atomicAdd(&s_SHist[s], 1); + } + } + } + } + __syncthreads(); + + for (int i = threadIdx.x; i <= scaleRange; i += blockDim.x) + ::atomicAdd(SHist + i, s_SHist[i]); + } + + void Guil_Full_calcSHist_gpu(const int* templSizes, const int* imageSizes, int* SHist, + float angle, float angleEpsilon, + float minScale, float maxScale, float iScaleStep, int scaleRange, + int levels, int tMaxSize) + { + const dim3 block(256); + const dim3 grid(tMaxSize, levels + 1); + + angle *= (CV_PI_F / 180.0f); + angleEpsilon *= (CV_PI_F / 180.0f); + + const size_t smemSize = (scaleRange + 1) * sizeof(float); + + Guil_Full_calcSHist<<>>(templSizes, imageSizes, SHist, + angle, angleEpsilon, + minScale, maxScale, iScaleStep, scaleRange); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + } + + __global__ void Guil_Full_calcPHist(const int* templSizes, const int* imageSizes, PtrStepSzi PHist, + const float angle, const float sinVal, const float cosVal, const float angleEpsilon, const float scale, + const float idp) + { + const int tIdx = blockIdx.x; + const int level = blockIdx.y; + + const int tSize = templSizes[level]; + + if (tIdx < tSize) + { + const int imSize = imageSizes[level]; + + const float t_p1_theta = TemplFeatureTable::p1_theta(level)[tIdx] + angle; + + float2 r1 = TemplFeatureTable::r1(level)[tIdx]; + float2 r2 = TemplFeatureTable::r2(level)[tIdx]; + + r1 = r1 * scale; + r2 = r2 * scale; + + r1 = make_float2(cosVal * r1.x - sinVal * r1.y, sinVal * r1.x + cosVal * r1.y); + r2 = make_float2(cosVal * r2.x - sinVal * r2.y, sinVal * r2.x + cosVal * r2.y); + + for (int i = threadIdx.x; i < imSize; i += blockDim.x) + { + const float im_p1_theta = ImageFeatureTable::p1_theta(level)[i]; + + const float2 im_p1_pos = ImageFeatureTable::p1_pos(level)[i]; + const float2 im_p2_pos = ImageFeatureTable::p2_pos(level)[i]; + + if (angleEq(im_p1_theta, t_p1_theta, angleEpsilon)) + { + float2 c1, c2; + + c1 = im_p1_pos - r1; + c1 = c1 * idp; + + c2 = im_p2_pos - r2; + c2 = c2 * idp; + + if (::fabs(c1.x - c2.x) > 1 || ::fabs(c1.y - c2.y) > 1) + continue; + + if (c1.y >= 0 && c1.y < PHist.rows - 2 && c1.x >= 0 && c1.x < PHist.cols - 2) + ::atomicAdd(PHist.ptr(__float2int_rn(c1.y) + 1) + __float2int_rn(c1.x) + 1, 1); + } + } + } + } + + void Guil_Full_calcPHist_gpu(const int* templSizes, const int* imageSizes, PtrStepSzi PHist, + float angle, float angleEpsilon, float scale, + float dp, + int levels, int tMaxSize) + { + const dim3 block(256); + const dim3 grid(tMaxSize, levels + 1); + + angle *= (CV_PI_F / 180.0f); + angleEpsilon *= (CV_PI_F / 180.0f); + + const float sinVal = ::sinf(angle); + const float cosVal = ::cosf(angle); + + cudaSafeCall( cudaFuncSetCacheConfig(Guil_Full_calcPHist, cudaFuncCachePreferL1) ); + + Guil_Full_calcPHist<<>>(templSizes, imageSizes, PHist, + angle, sinVal, cosVal, angleEpsilon, scale, + 1.0f / dp); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + } + + __global__ void Guil_Full_findPosInHist(const PtrStepSzi hist, float4* out, int3* votes, const int maxSize, + const float angle, const int angleVotes, const float scale, const int scaleVotes, + const float dp, const int threshold) + { + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= hist.cols - 2 || y >= hist.rows - 2) + return; + + const int curVotes = hist(y + 1, x + 1); + + if (curVotes > threshold && + curVotes > hist(y + 1, x) && + curVotes >= hist(y + 1, x + 2) && + curVotes > hist(y, x + 1) && + curVotes >= hist(y + 2, x + 1)) + { + const int ind = ::atomicAdd(&g_counter, 1); + + if (ind < maxSize) + { + out[ind] = make_float4(x * dp, y * dp, scale, angle); + votes[ind] = make_int3(curVotes, scaleVotes, angleVotes); + } + } + } + + int Guil_Full_findPosInHist_gpu(PtrStepSzi hist, float4* out, int3* votes, int curSize, int maxSize, + float angle, int angleVotes, float scale, int scaleVotes, + float dp, int threshold) + { + void* counterPtr; + cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); + + cudaSafeCall( cudaMemcpy(counterPtr, &curSize, sizeof(int), cudaMemcpyHostToDevice) ); + + const dim3 block(32, 8); + const dim3 grid(divUp(hist.cols - 2, block.x), divUp(hist.rows - 2, block.y)); + + cudaSafeCall( cudaFuncSetCacheConfig(Guil_Full_findPosInHist, cudaFuncCachePreferL1) ); + + Guil_Full_findPosInHist<<>>(hist, out, votes, maxSize, + angle, angleVotes, scale, scaleVotes, + dp, threshold); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + int totalCount; + cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); + + totalCount = ::min(totalCount, maxSize); + + return totalCount; + } + } +}}} + +#endif // HAVE_OPENCV_GPUARITHM + +#endif /* CUDA_DISABLER */ diff --git a/modules/gpuimgproc/src/cuda/hist.cu b/modules/gpuimgproc/src/cuda/hist.cu index 474c27cf7..51931d7ce 100644 --- a/modules/gpuimgproc/src/cuda/hist.cu +++ b/modules/gpuimgproc/src/cuda/hist.cu @@ -109,6 +109,86 @@ namespace hist ///////////////////////////////////////////////////////////////////////// +namespace hist +{ + __device__ __forceinline__ void histEvenInc(int* shist, uint data, int binSize, int lowerLevel, int upperLevel) + { + if (data >= lowerLevel && data <= upperLevel) + { + const uint ind = (data - lowerLevel) / binSize; + Emulation::smem::atomicAdd(shist + ind, 1); + } + } + + __global__ void histEven8u(const uchar* src, const size_t step, const int rows, const int cols, + int* hist, const int binCount, const int binSize, const int lowerLevel, const int upperLevel) + { + extern __shared__ int shist[]; + + const int y = blockIdx.x * blockDim.y + threadIdx.y; + const int tid = threadIdx.y * blockDim.x + threadIdx.x; + + if (tid < binCount) + shist[tid] = 0; + + __syncthreads(); + + if (y < rows) + { + const uchar* rowPtr = src + y * step; + const uint* rowPtr4 = (uint*) rowPtr; + + const int cols_4 = cols / 4; + for (int x = threadIdx.x; x < cols_4; x += blockDim.x) + { + const uint data = rowPtr4[x]; + + histEvenInc(shist, (data >> 0) & 0xFFU, binSize, lowerLevel, upperLevel); + histEvenInc(shist, (data >> 8) & 0xFFU, binSize, lowerLevel, upperLevel); + histEvenInc(shist, (data >> 16) & 0xFFU, binSize, lowerLevel, upperLevel); + histEvenInc(shist, (data >> 24) & 0xFFU, binSize, lowerLevel, upperLevel); + } + + if (cols % 4 != 0 && threadIdx.x == 0) + { + for (int x = cols_4 * 4; x < cols; ++x) + { + const uchar data = rowPtr[x]; + histEvenInc(shist, data, binSize, lowerLevel, upperLevel); + } + } + } + + __syncthreads(); + + if (tid < binCount) + { + const int histVal = shist[tid]; + + if (histVal > 0) + ::atomicAdd(hist + tid, histVal); + } + } + + void histEven8u(PtrStepSzb src, int* hist, int binCount, int lowerLevel, int upperLevel, cudaStream_t stream) + { + const dim3 block(32, 8); + const dim3 grid(divUp(src.rows, block.y)); + + const int binSize = divUp(upperLevel - lowerLevel, binCount); + + const size_t smem_size = binCount * sizeof(int); + + histEven8u<<>>(src.data, src.step, src.rows, src.cols, hist, binCount, binSize, lowerLevel, upperLevel); + cudaSafeCall( cudaGetLastError() ); + + if (stream == 0) + cudaSafeCall( cudaDeviceSynchronize() ); + } +} + +///////////////////////////////////////////////////////////////////////// + namespace hist { __constant__ int c_lut[256]; diff --git a/modules/gpuimgproc/src/cuda/hough.cu b/modules/gpuimgproc/src/cuda/hough.cu deleted file mode 100644 index 696ed3845..000000000 --- a/modules/gpuimgproc/src/cuda/hough.cu +++ /dev/null @@ -1,1710 +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 "opencv2/core/cuda/common.hpp" -#include "opencv2/core/cuda/emulation.hpp" -#include "opencv2/core/cuda/vec_math.hpp" -#include "opencv2/core/cuda/functional.hpp" -#include "opencv2/core/cuda/limits.hpp" -#include "opencv2/core/cuda/dynamic_smem.hpp" - -namespace cv { namespace gpu { namespace cudev -{ - namespace hough - { - __device__ int g_counter; - - //////////////////////////////////////////////////////////////////////// - // buildPointList - - template - __global__ void buildPointList(const PtrStepSzb src, unsigned int* list) - { - __shared__ unsigned int s_queues[4][32 * PIXELS_PER_THREAD]; - __shared__ int s_qsize[4]; - __shared__ int s_globStart[4]; - - const int x = blockIdx.x * blockDim.x * PIXELS_PER_THREAD + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (threadIdx.x == 0) - s_qsize[threadIdx.y] = 0; - __syncthreads(); - - if (y < src.rows) - { - // fill the queue - const uchar* srcRow = src.ptr(y); - for (int i = 0, xx = x; i < PIXELS_PER_THREAD && xx < src.cols; ++i, xx += blockDim.x) - { - if (srcRow[xx]) - { - const unsigned int val = (y << 16) | xx; - const int qidx = Emulation::smem::atomicAdd(&s_qsize[threadIdx.y], 1); - s_queues[threadIdx.y][qidx] = val; - } - } - } - - __syncthreads(); - - // let one thread reserve the space required in the global list - if (threadIdx.x == 0 && threadIdx.y == 0) - { - // find how many items are stored in each list - int totalSize = 0; - for (int i = 0; i < blockDim.y; ++i) - { - s_globStart[i] = totalSize; - totalSize += s_qsize[i]; - } - - // calculate the offset in the global list - const int globalOffset = atomicAdd(&g_counter, totalSize); - for (int i = 0; i < blockDim.y; ++i) - s_globStart[i] += globalOffset; - } - - __syncthreads(); - - // copy local queues to global queue - const int qsize = s_qsize[threadIdx.y]; - int gidx = s_globStart[threadIdx.y] + threadIdx.x; - for(int i = threadIdx.x; i < qsize; i += blockDim.x, gidx += blockDim.x) - list[gidx] = s_queues[threadIdx.y][i]; - } - - int buildPointList_gpu(PtrStepSzb src, unsigned int* list) - { - const int PIXELS_PER_THREAD = 16; - - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(32, 4); - const dim3 grid(divUp(src.cols, block.x * PIXELS_PER_THREAD), divUp(src.rows, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(buildPointList, cudaFuncCachePreferShared) ); - - buildPointList<<>>(src, list); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - return totalCount; - } - - //////////////////////////////////////////////////////////////////////// - // linesAccum - - __global__ void linesAccumGlobal(const unsigned int* list, const int count, PtrStepi accum, const float irho, const float theta, const int numrho) - { - const int n = blockIdx.x; - const float ang = n * theta; - - float sinVal; - float cosVal; - sincosf(ang, &sinVal, &cosVal); - sinVal *= irho; - cosVal *= irho; - - const int shift = (numrho - 1) / 2; - - int* accumRow = accum.ptr(n + 1); - for (int i = threadIdx.x; i < count; i += blockDim.x) - { - const unsigned int val = list[i]; - - const int x = (val & 0xFFFF); - const int y = (val >> 16) & 0xFFFF; - - int r = __float2int_rn(x * cosVal + y * sinVal); - r += shift; - - ::atomicAdd(accumRow + r + 1, 1); - } - } - - __global__ void linesAccumShared(const unsigned int* list, const int count, PtrStepi accum, const float irho, const float theta, const int numrho) - { - int* smem = DynamicSharedMem(); - - for (int i = threadIdx.x; i < numrho + 1; i += blockDim.x) - smem[i] = 0; - - __syncthreads(); - - const int n = blockIdx.x; - const float ang = n * theta; - - float sinVal; - float cosVal; - sincosf(ang, &sinVal, &cosVal); - sinVal *= irho; - cosVal *= irho; - - const int shift = (numrho - 1) / 2; - - for (int i = threadIdx.x; i < count; i += blockDim.x) - { - const unsigned int val = list[i]; - - const int x = (val & 0xFFFF); - const int y = (val >> 16) & 0xFFFF; - - int r = __float2int_rn(x * cosVal + y * sinVal); - r += shift; - - Emulation::smem::atomicAdd(&smem[r + 1], 1); - } - - __syncthreads(); - - int* accumRow = accum.ptr(n + 1); - for (int i = threadIdx.x; i < numrho + 1; i += blockDim.x) - accumRow[i] = smem[i]; - } - - void linesAccum_gpu(const unsigned int* list, int count, PtrStepSzi accum, float rho, float theta, size_t sharedMemPerBlock, bool has20) - { - const dim3 block(has20 ? 1024 : 512); - const dim3 grid(accum.rows - 2); - - size_t smemSize = (accum.cols - 1) * sizeof(int); - - if (smemSize < sharedMemPerBlock - 1000) - linesAccumShared<<>>(list, count, accum, 1.0f / rho, theta, accum.cols - 2); - else - linesAccumGlobal<<>>(list, count, accum, 1.0f / rho, theta, accum.cols - 2); - - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - - //////////////////////////////////////////////////////////////////////// - // linesGetResult - - __global__ void linesGetResult(const PtrStepSzi accum, float2* out, int* votes, const int maxSize, const float rho, const float theta, const int threshold, const int numrho) - { - const int r = blockIdx.x * blockDim.x + threadIdx.x; - const int n = blockIdx.y * blockDim.y + threadIdx.y; - - if (r >= accum.cols - 2 || n >= accum.rows - 2) - return; - - const int curVotes = accum(n + 1, r + 1); - - if (curVotes > threshold && - curVotes > accum(n + 1, r) && - curVotes >= accum(n + 1, r + 2) && - curVotes > accum(n, r + 1) && - curVotes >= accum(n + 2, r + 1)) - { - const float radius = (r - (numrho - 1) * 0.5f) * rho; - const float angle = n * theta; - - const int ind = ::atomicAdd(&g_counter, 1); - if (ind < maxSize) - { - out[ind] = make_float2(radius, angle); - votes[ind] = curVotes; - } - } - } - - int linesGetResult_gpu(PtrStepSzi accum, float2* out, int* votes, int maxSize, float rho, float theta, int threshold, bool doSort) - { - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(32, 8); - const dim3 grid(divUp(accum.cols - 2, block.x), divUp(accum.rows - 2, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(linesGetResult, cudaFuncCachePreferL1) ); - - linesGetResult<<>>(accum, out, votes, maxSize, rho, theta, threshold, accum.cols - 2); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - totalCount = ::min(totalCount, maxSize); - - if (doSort && totalCount > 0) - { - thrust::device_ptr outPtr(out); - thrust::device_ptr votesPtr(votes); - thrust::sort_by_key(votesPtr, votesPtr + totalCount, outPtr, thrust::greater()); - } - - return totalCount; - } - - //////////////////////////////////////////////////////////////////////// - // houghLinesProbabilistic - - texture tex_mask(false, cudaFilterModePoint, cudaAddressModeClamp); - - __global__ void houghLinesProbabilistic(const PtrStepSzi accum, - int4* out, const int maxSize, - const float rho, const float theta, - const int lineGap, const int lineLength, - const int rows, const int cols) - { - const int r = blockIdx.x * blockDim.x + threadIdx.x; - const int n = blockIdx.y * blockDim.y + threadIdx.y; - - if (r >= accum.cols - 2 || n >= accum.rows - 2) - return; - - const int curVotes = accum(n + 1, r + 1); - - if (curVotes >= lineLength && - curVotes > accum(n, r) && - curVotes > accum(n, r + 1) && - curVotes > accum(n, r + 2) && - curVotes > accum(n + 1, r) && - curVotes > accum(n + 1, r + 2) && - curVotes > accum(n + 2, r) && - curVotes > accum(n + 2, r + 1) && - curVotes > accum(n + 2, r + 2)) - { - const float radius = (r - (accum.cols - 2 - 1) * 0.5f) * rho; - const float angle = n * theta; - - float cosa; - float sina; - sincosf(angle, &sina, &cosa); - - float2 p0 = make_float2(cosa * radius, sina * radius); - float2 dir = make_float2(-sina, cosa); - - float2 pb[4] = {make_float2(-1, -1), make_float2(-1, -1), make_float2(-1, -1), make_float2(-1, -1)}; - float a; - - if (dir.x != 0) - { - a = -p0.x / dir.x; - pb[0].x = 0; - pb[0].y = p0.y + a * dir.y; - - a = (cols - 1 - p0.x) / dir.x; - pb[1].x = cols - 1; - pb[1].y = p0.y + a * dir.y; - } - if (dir.y != 0) - { - a = -p0.y / dir.y; - pb[2].x = p0.x + a * dir.x; - pb[2].y = 0; - - a = (rows - 1 - p0.y) / dir.y; - pb[3].x = p0.x + a * dir.x; - pb[3].y = rows - 1; - } - - if (pb[0].x == 0 && (pb[0].y >= 0 && pb[0].y < rows)) - { - p0 = pb[0]; - if (dir.x < 0) - dir = -dir; - } - else if (pb[1].x == cols - 1 && (pb[0].y >= 0 && pb[0].y < rows)) - { - p0 = pb[1]; - if (dir.x > 0) - dir = -dir; - } - else if (pb[2].y == 0 && (pb[2].x >= 0 && pb[2].x < cols)) - { - p0 = pb[2]; - if (dir.y < 0) - dir = -dir; - } - else if (pb[3].y == rows - 1 && (pb[3].x >= 0 && pb[3].x < cols)) - { - p0 = pb[3]; - if (dir.y > 0) - dir = -dir; - } - - float2 d; - if (::fabsf(dir.x) > ::fabsf(dir.y)) - { - d.x = dir.x > 0 ? 1 : -1; - d.y = dir.y / ::fabsf(dir.x); - } - else - { - d.x = dir.x / ::fabsf(dir.y); - d.y = dir.y > 0 ? 1 : -1; - } - - float2 line_end[2]; - int gap; - bool inLine = false; - - float2 p1 = p0; - if (p1.x < 0 || p1.x >= cols || p1.y < 0 || p1.y >= rows) - return; - - for (;;) - { - if (tex2D(tex_mask, p1.x, p1.y)) - { - gap = 0; - - if (!inLine) - { - line_end[0] = p1; - line_end[1] = p1; - inLine = true; - } - else - { - line_end[1] = p1; - } - } - else if (inLine) - { - if (++gap > lineGap) - { - bool good_line = ::abs(line_end[1].x - line_end[0].x) >= lineLength || - ::abs(line_end[1].y - line_end[0].y) >= lineLength; - - if (good_line) - { - const int ind = ::atomicAdd(&g_counter, 1); - if (ind < maxSize) - out[ind] = make_int4(line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y); - } - - gap = 0; - inLine = false; - } - } - - p1 = p1 + d; - if (p1.x < 0 || p1.x >= cols || p1.y < 0 || p1.y >= rows) - { - if (inLine) - { - bool good_line = ::abs(line_end[1].x - line_end[0].x) >= lineLength || - ::abs(line_end[1].y - line_end[0].y) >= lineLength; - - if (good_line) - { - const int ind = ::atomicAdd(&g_counter, 1); - if (ind < maxSize) - out[ind] = make_int4(line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y); - } - - } - break; - } - } - } - } - - int houghLinesProbabilistic_gpu(PtrStepSzb mask, PtrStepSzi accum, int4* out, int maxSize, float rho, float theta, int lineGap, int lineLength) - { - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(32, 8); - const dim3 grid(divUp(accum.cols - 2, block.x), divUp(accum.rows - 2, block.y)); - - bindTexture(&tex_mask, mask); - - houghLinesProbabilistic<<>>(accum, - out, maxSize, - rho, theta, - lineGap, lineLength, - mask.rows, mask.cols); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - totalCount = ::min(totalCount, maxSize); - - return totalCount; - } - - //////////////////////////////////////////////////////////////////////// - // circlesAccumCenters - - __global__ void circlesAccumCenters(const unsigned int* list, const int count, const PtrStepi dx, const PtrStepi dy, - PtrStepi accum, const int width, const int height, const int minRadius, const int maxRadius, const float idp) - { - const int SHIFT = 10; - const int ONE = 1 << SHIFT; - - const int tid = blockIdx.x * blockDim.x + threadIdx.x; - - if (tid >= count) - return; - - const unsigned int val = list[tid]; - - const int x = (val & 0xFFFF); - const int y = (val >> 16) & 0xFFFF; - - const int vx = dx(y, x); - const int vy = dy(y, x); - - if (vx == 0 && vy == 0) - return; - - const float mag = ::sqrtf(vx * vx + vy * vy); - - const int x0 = __float2int_rn((x * idp) * ONE); - const int y0 = __float2int_rn((y * idp) * ONE); - - int sx = __float2int_rn((vx * idp) * ONE / mag); - int sy = __float2int_rn((vy * idp) * ONE / mag); - - // Step from minRadius to maxRadius in both directions of the gradient - for (int k1 = 0; k1 < 2; ++k1) - { - int x1 = x0 + minRadius * sx; - int y1 = y0 + minRadius * sy; - - for (int r = minRadius; r <= maxRadius; x1 += sx, y1 += sy, ++r) - { - const int x2 = x1 >> SHIFT; - const int y2 = y1 >> SHIFT; - - if (x2 < 0 || x2 >= width || y2 < 0 || y2 >= height) - break; - - ::atomicAdd(accum.ptr(y2 + 1) + x2 + 1, 1); - } - - sx = -sx; - sy = -sy; - } - } - - void circlesAccumCenters_gpu(const unsigned int* list, int count, PtrStepi dx, PtrStepi dy, PtrStepSzi accum, int minRadius, int maxRadius, float idp) - { - const dim3 block(256); - const dim3 grid(divUp(count, block.x)); - - cudaSafeCall( cudaFuncSetCacheConfig(circlesAccumCenters, cudaFuncCachePreferL1) ); - - circlesAccumCenters<<>>(list, count, dx, dy, accum, accum.cols - 2, accum.rows - 2, minRadius, maxRadius, idp); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - - //////////////////////////////////////////////////////////////////////// - // buildCentersList - - __global__ void buildCentersList(const PtrStepSzi accum, unsigned int* centers, const int threshold) - { - const int x = blockIdx.x * blockDim.x + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (x < accum.cols - 2 && y < accum.rows - 2) - { - const int top = accum(y, x + 1); - - const int left = accum(y + 1, x); - const int cur = accum(y + 1, x + 1); - const int right = accum(y + 1, x + 2); - - const int bottom = accum(y + 2, x + 1); - - if (cur > threshold && cur > top && cur >= bottom && cur > left && cur >= right) - { - const unsigned int val = (y << 16) | x; - const int idx = ::atomicAdd(&g_counter, 1); - centers[idx] = val; - } - } - } - - int buildCentersList_gpu(PtrStepSzi accum, unsigned int* centers, int threshold) - { - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(32, 8); - const dim3 grid(divUp(accum.cols - 2, block.x), divUp(accum.rows - 2, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(buildCentersList, cudaFuncCachePreferL1) ); - - buildCentersList<<>>(accum, centers, threshold); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - return totalCount; - } - - //////////////////////////////////////////////////////////////////////// - // circlesAccumRadius - - __global__ void circlesAccumRadius(const unsigned int* centers, const unsigned int* list, const int count, - float3* circles, const int maxCircles, const float dp, - const int minRadius, const int maxRadius, const int histSize, const int threshold) - { - int* smem = DynamicSharedMem(); - - for (int i = threadIdx.x; i < histSize + 2; i += blockDim.x) - smem[i] = 0; - __syncthreads(); - - unsigned int val = centers[blockIdx.x]; - - float cx = (val & 0xFFFF); - float cy = (val >> 16) & 0xFFFF; - - cx = (cx + 0.5f) * dp; - cy = (cy + 0.5f) * dp; - - for (int i = threadIdx.x; i < count; i += blockDim.x) - { - val = list[i]; - - const int x = (val & 0xFFFF); - const int y = (val >> 16) & 0xFFFF; - - const float rad = ::sqrtf((cx - x) * (cx - x) + (cy - y) * (cy - y)); - if (rad >= minRadius && rad <= maxRadius) - { - const int r = __float2int_rn(rad - minRadius); - - Emulation::smem::atomicAdd(&smem[r + 1], 1); - } - } - - __syncthreads(); - - for (int i = threadIdx.x; i < histSize; i += blockDim.x) - { - const int curVotes = smem[i + 1]; - - if (curVotes >= threshold && curVotes > smem[i] && curVotes >= smem[i + 2]) - { - const int ind = ::atomicAdd(&g_counter, 1); - if (ind < maxCircles) - circles[ind] = make_float3(cx, cy, i + minRadius); - } - } - } - - int circlesAccumRadius_gpu(const unsigned int* centers, int centersCount, const unsigned int* list, int count, - float3* circles, int maxCircles, float dp, int minRadius, int maxRadius, int threshold, bool has20) - { - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(has20 ? 1024 : 512); - const dim3 grid(centersCount); - - const int histSize = maxRadius - minRadius + 1; - size_t smemSize = (histSize + 2) * sizeof(int); - - circlesAccumRadius<<>>(centers, list, count, circles, maxCircles, dp, minRadius, maxRadius, histSize, threshold); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - totalCount = ::min(totalCount, maxCircles); - - return totalCount; - } - - //////////////////////////////////////////////////////////////////////// - // Generalized Hough - - template - __global__ void buildEdgePointList(const PtrStepSzb edges, const PtrStep dx, const PtrStep dy, unsigned int* coordList, float* thetaList) - { - __shared__ unsigned int s_coordLists[4][32 * PIXELS_PER_THREAD]; - __shared__ float s_thetaLists[4][32 * PIXELS_PER_THREAD]; - __shared__ int s_sizes[4]; - __shared__ int s_globStart[4]; - - const int x = blockIdx.x * blockDim.x * PIXELS_PER_THREAD + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (threadIdx.x == 0) - s_sizes[threadIdx.y] = 0; - __syncthreads(); - - if (y < edges.rows) - { - // fill the queue - const uchar* edgesRow = edges.ptr(y); - const T* dxRow = dx.ptr(y); - const T* dyRow = dy.ptr(y); - - for (int i = 0, xx = x; i < PIXELS_PER_THREAD && xx < edges.cols; ++i, xx += blockDim.x) - { - const T dxVal = dxRow[xx]; - const T dyVal = dyRow[xx]; - - if (edgesRow[xx] && (dxVal != 0 || dyVal != 0)) - { - const unsigned int coord = (y << 16) | xx; - - float theta = ::atan2f(dyVal, dxVal); - if (theta < 0) - theta += 2.0f * CV_PI_F; - - const int qidx = Emulation::smem::atomicAdd(&s_sizes[threadIdx.y], 1); - - s_coordLists[threadIdx.y][qidx] = coord; - s_thetaLists[threadIdx.y][qidx] = theta; - } - } - } - - __syncthreads(); - - // let one thread reserve the space required in the global list - if (threadIdx.x == 0 && threadIdx.y == 0) - { - // find how many items are stored in each list - int totalSize = 0; - for (int i = 0; i < blockDim.y; ++i) - { - s_globStart[i] = totalSize; - totalSize += s_sizes[i]; - } - - // calculate the offset in the global list - const int globalOffset = atomicAdd(&g_counter, totalSize); - for (int i = 0; i < blockDim.y; ++i) - s_globStart[i] += globalOffset; - } - - __syncthreads(); - - // copy local queues to global queue - const int qsize = s_sizes[threadIdx.y]; - int gidx = s_globStart[threadIdx.y] + threadIdx.x; - for(int i = threadIdx.x; i < qsize; i += blockDim.x, gidx += blockDim.x) - { - coordList[gidx] = s_coordLists[threadIdx.y][i]; - thetaList[gidx] = s_thetaLists[threadIdx.y][i]; - } - } - - template - int buildEdgePointList_gpu(PtrStepSzb edges, PtrStepSzb dx, PtrStepSzb dy, unsigned int* coordList, float* thetaList) - { - const int PIXELS_PER_THREAD = 8; - - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(32, 4); - const dim3 grid(divUp(edges.cols, block.x * PIXELS_PER_THREAD), divUp(edges.rows, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(buildEdgePointList, cudaFuncCachePreferShared) ); - - buildEdgePointList<<>>(edges, (PtrStepSz) dx, (PtrStepSz) dy, coordList, thetaList); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - return totalCount; - } - - template int buildEdgePointList_gpu(PtrStepSzb edges, PtrStepSzb dx, PtrStepSzb dy, unsigned int* coordList, float* thetaList); - template int buildEdgePointList_gpu(PtrStepSzb edges, PtrStepSzb dx, PtrStepSzb dy, unsigned int* coordList, float* thetaList); - template int buildEdgePointList_gpu(PtrStepSzb edges, PtrStepSzb dx, PtrStepSzb dy, unsigned int* coordList, float* thetaList); - - __global__ void buildRTable(const unsigned int* coordList, const float* thetaList, const int pointsCount, - PtrStep r_table, int* r_sizes, int maxSize, - const short2 templCenter, const float thetaScale) - { - const int tid = blockIdx.x * blockDim.x + threadIdx.x; - - if (tid >= pointsCount) - return; - - const unsigned int coord = coordList[tid]; - short2 p; - p.x = (coord & 0xFFFF); - p.y = (coord >> 16) & 0xFFFF; - - const float theta = thetaList[tid]; - const int n = __float2int_rn(theta * thetaScale); - - const int ind = ::atomicAdd(r_sizes + n, 1); - if (ind < maxSize) - r_table(n, ind) = saturate_cast(p - templCenter); - } - - void buildRTable_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, - PtrStepSz r_table, int* r_sizes, - short2 templCenter, int levels) - { - const dim3 block(256); - const dim3 grid(divUp(pointsCount, block.x)); - - const float thetaScale = levels / (2.0f * CV_PI_F); - - buildRTable<<>>(coordList, thetaList, pointsCount, r_table, r_sizes, r_table.cols, templCenter, thetaScale); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - - //////////////////////////////////////////////////////////////////////// - // GHT_Ballard_Pos - - __global__ void GHT_Ballard_Pos_calcHist(const unsigned int* coordList, const float* thetaList, const int pointsCount, - const PtrStep r_table, const int* r_sizes, - PtrStepSzi hist, - const float idp, const float thetaScale) - { - const int tid = blockIdx.x * blockDim.x + threadIdx.x; - - if (tid >= pointsCount) - return; - - const unsigned int coord = coordList[tid]; - short2 p; - p.x = (coord & 0xFFFF); - p.y = (coord >> 16) & 0xFFFF; - - const float theta = thetaList[tid]; - const int n = __float2int_rn(theta * thetaScale); - - const short2* r_row = r_table.ptr(n); - const int r_row_size = r_sizes[n]; - - for (int j = 0; j < r_row_size; ++j) - { - int2 c = p - r_row[j]; - - c.x = __float2int_rn(c.x * idp); - c.y = __float2int_rn(c.y * idp); - - if (c.x >= 0 && c.x < hist.cols - 2 && c.y >= 0 && c.y < hist.rows - 2) - ::atomicAdd(hist.ptr(c.y + 1) + c.x + 1, 1); - } - } - - void GHT_Ballard_Pos_calcHist_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, - PtrStepSz r_table, const int* r_sizes, - PtrStepSzi hist, - float dp, int levels) - { - const dim3 block(256); - const dim3 grid(divUp(pointsCount, block.x)); - - const float idp = 1.0f / dp; - const float thetaScale = levels / (2.0f * CV_PI_F); - - GHT_Ballard_Pos_calcHist<<>>(coordList, thetaList, pointsCount, r_table, r_sizes, hist, idp, thetaScale); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - - __global__ void GHT_Ballard_Pos_findPosInHist(const PtrStepSzi hist, float4* out, int3* votes, const int maxSize, const float dp, const int threshold) - { - const int x = blockIdx.x * blockDim.x + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (x >= hist.cols - 2 || y >= hist.rows - 2) - return; - - const int curVotes = hist(y + 1, x + 1); - - if (curVotes > threshold && - curVotes > hist(y + 1, x) && - curVotes >= hist(y + 1, x + 2) && - curVotes > hist(y, x + 1) && - curVotes >= hist(y + 2, x + 1)) - { - const int ind = ::atomicAdd(&g_counter, 1); - - if (ind < maxSize) - { - out[ind] = make_float4(x * dp, y * dp, 1.0f, 0.0f); - votes[ind] = make_int3(curVotes, 0, 0); - } - } - } - - int GHT_Ballard_Pos_findPosInHist_gpu(PtrStepSzi hist, float4* out, int3* votes, int maxSize, float dp, int threshold) - { - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(32, 8); - const dim3 grid(divUp(hist.cols - 2, block.x), divUp(hist.rows - 2, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(GHT_Ballard_Pos_findPosInHist, cudaFuncCachePreferL1) ); - - GHT_Ballard_Pos_findPosInHist<<>>(hist, out, votes, maxSize, dp, threshold); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - totalCount = ::min(totalCount, maxSize); - - return totalCount; - } - - //////////////////////////////////////////////////////////////////////// - // GHT_Ballard_PosScale - - __global__ void GHT_Ballard_PosScale_calcHist(const unsigned int* coordList, const float* thetaList, - PtrStep r_table, const int* r_sizes, - PtrStepi hist, const int rows, const int cols, - const float minScale, const float scaleStep, const int scaleRange, - const float idp, const float thetaScale) - { - const unsigned int coord = coordList[blockIdx.x]; - float2 p; - p.x = (coord & 0xFFFF); - p.y = (coord >> 16) & 0xFFFF; - - const float theta = thetaList[blockIdx.x]; - const int n = __float2int_rn(theta * thetaScale); - - const short2* r_row = r_table.ptr(n); - const int r_row_size = r_sizes[n]; - - for (int j = 0; j < r_row_size; ++j) - { - const float2 d = saturate_cast(r_row[j]); - - for (int s = threadIdx.x; s < scaleRange; s += blockDim.x) - { - const float scale = minScale + s * scaleStep; - - float2 c = p - scale * d; - - c.x *= idp; - c.y *= idp; - - if (c.x >= 0 && c.x < cols && c.y >= 0 && c.y < rows) - ::atomicAdd(hist.ptr((s + 1) * (rows + 2) + __float2int_rn(c.y + 1)) + __float2int_rn(c.x + 1), 1); - } - } - } - - void GHT_Ballard_PosScale_calcHist_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, - PtrStepSz r_table, const int* r_sizes, - PtrStepi hist, int rows, int cols, - float minScale, float scaleStep, int scaleRange, - float dp, int levels) - { - const dim3 block(256); - const dim3 grid(pointsCount); - - const float idp = 1.0f / dp; - const float thetaScale = levels / (2.0f * CV_PI_F); - - GHT_Ballard_PosScale_calcHist<<>>(coordList, thetaList, - r_table, r_sizes, - hist, rows, cols, - minScale, scaleStep, scaleRange, - idp, thetaScale); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - - __global__ void GHT_Ballard_PosScale_findPosInHist(const PtrStepi hist, const int rows, const int cols, const int scaleRange, - float4* out, int3* votes, const int maxSize, - const float minScale, const float scaleStep, const float dp, const int threshold) - { - const int x = blockIdx.x * blockDim.x + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (x >= cols || y >= rows) - return; - - for (int s = 0; s < scaleRange; ++s) - { - const float scale = minScale + s * scaleStep; - - const int prevScaleIdx = (s) * (rows + 2); - const int curScaleIdx = (s + 1) * (rows + 2); - const int nextScaleIdx = (s + 2) * (rows + 2); - - const int curVotes = hist(curScaleIdx + y + 1, x + 1); - - if (curVotes > threshold && - curVotes > hist(curScaleIdx + y + 1, x) && - curVotes >= hist(curScaleIdx + y + 1, x + 2) && - curVotes > hist(curScaleIdx + y, x + 1) && - curVotes >= hist(curScaleIdx + y + 2, x + 1) && - curVotes > hist(prevScaleIdx + y + 1, x + 1) && - curVotes >= hist(nextScaleIdx + y + 1, x + 1)) - { - const int ind = ::atomicAdd(&g_counter, 1); - - if (ind < maxSize) - { - out[ind] = make_float4(x * dp, y * dp, scale, 0.0f); - votes[ind] = make_int3(curVotes, curVotes, 0); - } - } - } - } - - int GHT_Ballard_PosScale_findPosInHist_gpu(PtrStepi hist, int rows, int cols, int scaleRange, float4* out, int3* votes, int maxSize, - float minScale, float scaleStep, float dp, int threshold) - { - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(32, 8); - const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(GHT_Ballard_PosScale_findPosInHist, cudaFuncCachePreferL1) ); - - GHT_Ballard_PosScale_findPosInHist<<>>(hist, rows, cols, scaleRange, out, votes, maxSize, minScale, scaleStep, dp, threshold); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - totalCount = ::min(totalCount, maxSize); - - return totalCount; - } - - //////////////////////////////////////////////////////////////////////// - // GHT_Ballard_PosRotation - - __global__ void GHT_Ballard_PosRotation_calcHist(const unsigned int* coordList, const float* thetaList, - PtrStep r_table, const int* r_sizes, - PtrStepi hist, const int rows, const int cols, - const float minAngle, const float angleStep, const int angleRange, - const float idp, const float thetaScale) - { - const unsigned int coord = coordList[blockIdx.x]; - float2 p; - p.x = (coord & 0xFFFF); - p.y = (coord >> 16) & 0xFFFF; - - const float thetaVal = thetaList[blockIdx.x]; - - for (int a = threadIdx.x; a < angleRange; a += blockDim.x) - { - const float angle = (minAngle + a * angleStep) * (CV_PI_F / 180.0f); - float sinA, cosA; - sincosf(angle, &sinA, &cosA); - - float theta = thetaVal - angle; - if (theta < 0) - theta += 2.0f * CV_PI_F; - - const int n = __float2int_rn(theta * thetaScale); - - const short2* r_row = r_table.ptr(n); - const int r_row_size = r_sizes[n]; - - for (int j = 0; j < r_row_size; ++j) - { - const float2 d = saturate_cast(r_row[j]); - - const float2 dr = make_float2(d.x * cosA - d.y * sinA, d.x * sinA + d.y * cosA); - - float2 c = make_float2(p.x - dr.x, p.y - dr.y); - c.x *= idp; - c.y *= idp; - - if (c.x >= 0 && c.x < cols && c.y >= 0 && c.y < rows) - ::atomicAdd(hist.ptr((a + 1) * (rows + 2) + __float2int_rn(c.y + 1)) + __float2int_rn(c.x + 1), 1); - } - } - } - - void GHT_Ballard_PosRotation_calcHist_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, - PtrStepSz r_table, const int* r_sizes, - PtrStepi hist, int rows, int cols, - float minAngle, float angleStep, int angleRange, - float dp, int levels) - { - const dim3 block(256); - const dim3 grid(pointsCount); - - const float idp = 1.0f / dp; - const float thetaScale = levels / (2.0f * CV_PI_F); - - GHT_Ballard_PosRotation_calcHist<<>>(coordList, thetaList, - r_table, r_sizes, - hist, rows, cols, - minAngle, angleStep, angleRange, - idp, thetaScale); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - - __global__ void GHT_Ballard_PosRotation_findPosInHist(const PtrStepi hist, const int rows, const int cols, const int angleRange, - float4* out, int3* votes, const int maxSize, - const float minAngle, const float angleStep, const float dp, const int threshold) - { - const int x = blockIdx.x * blockDim.x + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (x >= cols || y >= rows) - return; - - for (int a = 0; a < angleRange; ++a) - { - const float angle = minAngle + a * angleStep; - - const int prevAngleIdx = (a) * (rows + 2); - const int curAngleIdx = (a + 1) * (rows + 2); - const int nextAngleIdx = (a + 2) * (rows + 2); - - const int curVotes = hist(curAngleIdx + y + 1, x + 1); - - if (curVotes > threshold && - curVotes > hist(curAngleIdx + y + 1, x) && - curVotes >= hist(curAngleIdx + y + 1, x + 2) && - curVotes > hist(curAngleIdx + y, x + 1) && - curVotes >= hist(curAngleIdx + y + 2, x + 1) && - curVotes > hist(prevAngleIdx + y + 1, x + 1) && - curVotes >= hist(nextAngleIdx + y + 1, x + 1)) - { - const int ind = ::atomicAdd(&g_counter, 1); - - if (ind < maxSize) - { - out[ind] = make_float4(x * dp, y * dp, 1.0f, angle); - votes[ind] = make_int3(curVotes, 0, curVotes); - } - } - } - } - - int GHT_Ballard_PosRotation_findPosInHist_gpu(PtrStepi hist, int rows, int cols, int angleRange, float4* out, int3* votes, int maxSize, - float minAngle, float angleStep, float dp, int threshold) - { - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); - - const dim3 block(32, 8); - const dim3 grid(divUp(cols, block.x), divUp(rows, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(GHT_Ballard_PosRotation_findPosInHist, cudaFuncCachePreferL1) ); - - GHT_Ballard_PosRotation_findPosInHist<<>>(hist, rows, cols, angleRange, out, votes, maxSize, minAngle, angleStep, dp, threshold); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - totalCount = ::min(totalCount, maxSize); - - return totalCount; - } - - //////////////////////////////////////////////////////////////////////// - // GHT_Guil_Full - - struct FeatureTable - { - uchar* p1_pos_data; - size_t p1_pos_step; - - uchar* p1_theta_data; - size_t p1_theta_step; - - uchar* p2_pos_data; - size_t p2_pos_step; - - uchar* d12_data; - size_t d12_step; - - uchar* r1_data; - size_t r1_step; - - uchar* r2_data; - size_t r2_step; - }; - - __constant__ FeatureTable c_templFeatures; - __constant__ FeatureTable c_imageFeatures; - - void GHT_Guil_Full_setTemplFeatures(PtrStepb p1_pos, PtrStepb p1_theta, PtrStepb p2_pos, PtrStepb d12, PtrStepb r1, PtrStepb r2) - { - FeatureTable tbl; - - tbl.p1_pos_data = p1_pos.data; - tbl.p1_pos_step = p1_pos.step; - - tbl.p1_theta_data = p1_theta.data; - tbl.p1_theta_step = p1_theta.step; - - tbl.p2_pos_data = p2_pos.data; - tbl.p2_pos_step = p2_pos.step; - - tbl.d12_data = d12.data; - tbl.d12_step = d12.step; - - tbl.r1_data = r1.data; - tbl.r1_step = r1.step; - - tbl.r2_data = r2.data; - tbl.r2_step = r2.step; - - cudaSafeCall( cudaMemcpyToSymbol(c_templFeatures, &tbl, sizeof(FeatureTable)) ); - } - void GHT_Guil_Full_setImageFeatures(PtrStepb p1_pos, PtrStepb p1_theta, PtrStepb p2_pos, PtrStepb d12, PtrStepb r1, PtrStepb r2) - { - FeatureTable tbl; - - tbl.p1_pos_data = p1_pos.data; - tbl.p1_pos_step = p1_pos.step; - - tbl.p1_theta_data = p1_theta.data; - tbl.p1_theta_step = p1_theta.step; - - tbl.p2_pos_data = p2_pos.data; - tbl.p2_pos_step = p2_pos.step; - - tbl.d12_data = d12.data; - tbl.d12_step = d12.step; - - tbl.r1_data = r1.data; - tbl.r1_step = r1.step; - - tbl.r2_data = r2.data; - tbl.r2_step = r2.step; - - cudaSafeCall( cudaMemcpyToSymbol(c_imageFeatures, &tbl, sizeof(FeatureTable)) ); - } - - struct TemplFeatureTable - { - static __device__ float2* p1_pos(int n) - { - return (float2*)(c_templFeatures.p1_pos_data + n * c_templFeatures.p1_pos_step); - } - static __device__ float* p1_theta(int n) - { - return (float*)(c_templFeatures.p1_theta_data + n * c_templFeatures.p1_theta_step); - } - static __device__ float2* p2_pos(int n) - { - return (float2*)(c_templFeatures.p2_pos_data + n * c_templFeatures.p2_pos_step); - } - - static __device__ float* d12(int n) - { - return (float*)(c_templFeatures.d12_data + n * c_templFeatures.d12_step); - } - - static __device__ float2* r1(int n) - { - return (float2*)(c_templFeatures.r1_data + n * c_templFeatures.r1_step); - } - static __device__ float2* r2(int n) - { - return (float2*)(c_templFeatures.r2_data + n * c_templFeatures.r2_step); - } - }; - struct ImageFeatureTable - { - static __device__ float2* p1_pos(int n) - { - return (float2*)(c_imageFeatures.p1_pos_data + n * c_imageFeatures.p1_pos_step); - } - static __device__ float* p1_theta(int n) - { - return (float*)(c_imageFeatures.p1_theta_data + n * c_imageFeatures.p1_theta_step); - } - static __device__ float2* p2_pos(int n) - { - return (float2*)(c_imageFeatures.p2_pos_data + n * c_imageFeatures.p2_pos_step); - } - - static __device__ float* d12(int n) - { - return (float*)(c_imageFeatures.d12_data + n * c_imageFeatures.d12_step); - } - - static __device__ float2* r1(int n) - { - return (float2*)(c_imageFeatures.r1_data + n * c_imageFeatures.r1_step); - } - static __device__ float2* r2(int n) - { - return (float2*)(c_imageFeatures.r2_data + n * c_imageFeatures.r2_step); - } - }; - - __device__ float clampAngle(float a) - { - float res = a; - - while (res > 2.0f * CV_PI_F) - res -= 2.0f * CV_PI_F; - while (res < 0.0f) - res += 2.0f * CV_PI_F; - - return res; - } - - __device__ bool angleEq(float a, float b, float eps) - { - return (::fabs(clampAngle(a - b)) <= eps); - } - - template - __global__ void GHT_Guil_Full_buildFeatureList(const unsigned int* coordList, const float* thetaList, const int pointsCount, - int* sizes, const int maxSize, - const float xi, const float angleEpsilon, const float alphaScale, - const float2 center, const float maxDist) - { - const float p1_theta = thetaList[blockIdx.x]; - const unsigned int coord1 = coordList[blockIdx.x]; - float2 p1_pos; - p1_pos.x = (coord1 & 0xFFFF); - p1_pos.y = (coord1 >> 16) & 0xFFFF; - - for (int i = threadIdx.x; i < pointsCount; i += blockDim.x) - { - const float p2_theta = thetaList[i]; - const unsigned int coord2 = coordList[i]; - float2 p2_pos; - p2_pos.x = (coord2 & 0xFFFF); - p2_pos.y = (coord2 >> 16) & 0xFFFF; - - if (angleEq(p1_theta - p2_theta, xi, angleEpsilon)) - { - const float2 d = p1_pos - p2_pos; - - float alpha12 = clampAngle(::atan2(d.y, d.x) - p1_theta); - float d12 = ::sqrtf(d.x * d.x + d.y * d.y); - - if (d12 > maxDist) - continue; - - float2 r1 = p1_pos - center; - float2 r2 = p2_pos - center; - - const int n = __float2int_rn(alpha12 * alphaScale); - - const int ind = ::atomicAdd(sizes + n, 1); - - if (ind < maxSize) - { - if (!isTempl) - { - FT::p1_pos(n)[ind] = p1_pos; - FT::p2_pos(n)[ind] = p2_pos; - } - - FT::p1_theta(n)[ind] = p1_theta; - - FT::d12(n)[ind] = d12; - - if (isTempl) - { - FT::r1(n)[ind] = r1; - FT::r2(n)[ind] = r2; - } - } - } - } - } - - template - void GHT_Guil_Full_buildFeatureList_caller(const unsigned int* coordList, const float* thetaList, int pointsCount, - int* sizes, int maxSize, - float xi, float angleEpsilon, int levels, - float2 center, float maxDist) - { - const dim3 block(256); - const dim3 grid(pointsCount); - - const float alphaScale = levels / (2.0f * CV_PI_F); - - GHT_Guil_Full_buildFeatureList<<>>(coordList, thetaList, pointsCount, - sizes, maxSize, - xi * (CV_PI_F / 180.0f), angleEpsilon * (CV_PI_F / 180.0f), alphaScale, - center, maxDist); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - thrust::device_ptr sizesPtr(sizes); - thrust::transform(sizesPtr, sizesPtr + levels + 1, sizesPtr, cudev::bind2nd(cudev::minimum(), maxSize)); - } - - void GHT_Guil_Full_buildTemplFeatureList_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, - int* sizes, int maxSize, - float xi, float angleEpsilon, int levels, - float2 center, float maxDist) - { - GHT_Guil_Full_buildFeatureList_caller(coordList, thetaList, pointsCount, - sizes, maxSize, - xi, angleEpsilon, levels, - center, maxDist); - } - void GHT_Guil_Full_buildImageFeatureList_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, - int* sizes, int maxSize, - float xi, float angleEpsilon, int levels, - float2 center, float maxDist) - { - GHT_Guil_Full_buildFeatureList_caller(coordList, thetaList, pointsCount, - sizes, maxSize, - xi, angleEpsilon, levels, - center, maxDist); - } - - __global__ void GHT_Guil_Full_calcOHist(const int* templSizes, const int* imageSizes, int* OHist, - const float minAngle, const float maxAngle, const float iAngleStep, const int angleRange) - { - extern __shared__ int s_OHist[]; - for (int i = threadIdx.x; i <= angleRange; i += blockDim.x) - s_OHist[i] = 0; - __syncthreads(); - - const int tIdx = blockIdx.x; - const int level = blockIdx.y; - - const int tSize = templSizes[level]; - - if (tIdx < tSize) - { - const int imSize = imageSizes[level]; - - const float t_p1_theta = TemplFeatureTable::p1_theta(level)[tIdx]; - - for (int i = threadIdx.x; i < imSize; i += blockDim.x) - { - const float im_p1_theta = ImageFeatureTable::p1_theta(level)[i]; - - const float angle = clampAngle(im_p1_theta - t_p1_theta); - - if (angle >= minAngle && angle <= maxAngle) - { - const int n = __float2int_rn((angle - minAngle) * iAngleStep); - Emulation::smem::atomicAdd(&s_OHist[n], 1); - } - } - } - __syncthreads(); - - for (int i = threadIdx.x; i <= angleRange; i += blockDim.x) - ::atomicAdd(OHist + i, s_OHist[i]); - } - - void GHT_Guil_Full_calcOHist_gpu(const int* templSizes, const int* imageSizes, int* OHist, - float minAngle, float maxAngle, float angleStep, int angleRange, - int levels, int tMaxSize) - { - const dim3 block(256); - const dim3 grid(tMaxSize, levels + 1); - - minAngle *= (CV_PI_F / 180.0f); - maxAngle *= (CV_PI_F / 180.0f); - angleStep *= (CV_PI_F / 180.0f); - - const size_t smemSize = (angleRange + 1) * sizeof(float); - - GHT_Guil_Full_calcOHist<<>>(templSizes, imageSizes, OHist, - minAngle, maxAngle, 1.0f / angleStep, angleRange); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - - __global__ void GHT_Guil_Full_calcSHist(const int* templSizes, const int* imageSizes, int* SHist, - const float angle, const float angleEpsilon, - const float minScale, const float maxScale, const float iScaleStep, const int scaleRange) - { - extern __shared__ int s_SHist[]; - for (int i = threadIdx.x; i <= scaleRange; i += blockDim.x) - s_SHist[i] = 0; - __syncthreads(); - - const int tIdx = blockIdx.x; - const int level = blockIdx.y; - - const int tSize = templSizes[level]; - - if (tIdx < tSize) - { - const int imSize = imageSizes[level]; - - const float t_p1_theta = TemplFeatureTable::p1_theta(level)[tIdx] + angle; - const float t_d12 = TemplFeatureTable::d12(level)[tIdx] + angle; - - for (int i = threadIdx.x; i < imSize; i += blockDim.x) - { - const float im_p1_theta = ImageFeatureTable::p1_theta(level)[i]; - const float im_d12 = ImageFeatureTable::d12(level)[i]; - - if (angleEq(im_p1_theta, t_p1_theta, angleEpsilon)) - { - const float scale = im_d12 / t_d12; - - if (scale >= minScale && scale <= maxScale) - { - const int s = __float2int_rn((scale - minScale) * iScaleStep); - Emulation::smem::atomicAdd(&s_SHist[s], 1); - } - } - } - } - __syncthreads(); - - for (int i = threadIdx.x; i <= scaleRange; i += blockDim.x) - ::atomicAdd(SHist + i, s_SHist[i]); - } - - void GHT_Guil_Full_calcSHist_gpu(const int* templSizes, const int* imageSizes, int* SHist, - float angle, float angleEpsilon, - float minScale, float maxScale, float iScaleStep, int scaleRange, - int levels, int tMaxSize) - { - const dim3 block(256); - const dim3 grid(tMaxSize, levels + 1); - - angle *= (CV_PI_F / 180.0f); - angleEpsilon *= (CV_PI_F / 180.0f); - - const size_t smemSize = (scaleRange + 1) * sizeof(float); - - GHT_Guil_Full_calcSHist<<>>(templSizes, imageSizes, SHist, - angle, angleEpsilon, - minScale, maxScale, iScaleStep, scaleRange); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - - __global__ void GHT_Guil_Full_calcPHist(const int* templSizes, const int* imageSizes, PtrStepSzi PHist, - const float angle, const float sinVal, const float cosVal, const float angleEpsilon, const float scale, - const float idp) - { - const int tIdx = blockIdx.x; - const int level = blockIdx.y; - - const int tSize = templSizes[level]; - - if (tIdx < tSize) - { - const int imSize = imageSizes[level]; - - const float t_p1_theta = TemplFeatureTable::p1_theta(level)[tIdx] + angle; - - float2 r1 = TemplFeatureTable::r1(level)[tIdx]; - float2 r2 = TemplFeatureTable::r2(level)[tIdx]; - - r1 = r1 * scale; - r2 = r2 * scale; - - r1 = make_float2(cosVal * r1.x - sinVal * r1.y, sinVal * r1.x + cosVal * r1.y); - r2 = make_float2(cosVal * r2.x - sinVal * r2.y, sinVal * r2.x + cosVal * r2.y); - - for (int i = threadIdx.x; i < imSize; i += blockDim.x) - { - const float im_p1_theta = ImageFeatureTable::p1_theta(level)[i]; - - const float2 im_p1_pos = ImageFeatureTable::p1_pos(level)[i]; - const float2 im_p2_pos = ImageFeatureTable::p2_pos(level)[i]; - - if (angleEq(im_p1_theta, t_p1_theta, angleEpsilon)) - { - float2 c1, c2; - - c1 = im_p1_pos - r1; - c1 = c1 * idp; - - c2 = im_p2_pos - r2; - c2 = c2 * idp; - - if (::fabs(c1.x - c2.x) > 1 || ::fabs(c1.y - c2.y) > 1) - continue; - - if (c1.y >= 0 && c1.y < PHist.rows - 2 && c1.x >= 0 && c1.x < PHist.cols - 2) - ::atomicAdd(PHist.ptr(__float2int_rn(c1.y) + 1) + __float2int_rn(c1.x) + 1, 1); - } - } - } - } - - void GHT_Guil_Full_calcPHist_gpu(const int* templSizes, const int* imageSizes, PtrStepSzi PHist, - float angle, float angleEpsilon, float scale, - float dp, - int levels, int tMaxSize) - { - const dim3 block(256); - const dim3 grid(tMaxSize, levels + 1); - - angle *= (CV_PI_F / 180.0f); - angleEpsilon *= (CV_PI_F / 180.0f); - - const float sinVal = ::sinf(angle); - const float cosVal = ::cosf(angle); - - cudaSafeCall( cudaFuncSetCacheConfig(GHT_Guil_Full_calcPHist, cudaFuncCachePreferL1) ); - - GHT_Guil_Full_calcPHist<<>>(templSizes, imageSizes, PHist, - angle, sinVal, cosVal, angleEpsilon, scale, - 1.0f / dp); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - } - - __global__ void GHT_Guil_Full_findPosInHist(const PtrStepSzi hist, float4* out, int3* votes, const int maxSize, - const float angle, const int angleVotes, const float scale, const int scaleVotes, - const float dp, const int threshold) - { - const int x = blockIdx.x * blockDim.x + threadIdx.x; - const int y = blockIdx.y * blockDim.y + threadIdx.y; - - if (x >= hist.cols - 2 || y >= hist.rows - 2) - return; - - const int curVotes = hist(y + 1, x + 1); - - if (curVotes > threshold && - curVotes > hist(y + 1, x) && - curVotes >= hist(y + 1, x + 2) && - curVotes > hist(y, x + 1) && - curVotes >= hist(y + 2, x + 1)) - { - const int ind = ::atomicAdd(&g_counter, 1); - - if (ind < maxSize) - { - out[ind] = make_float4(x * dp, y * dp, scale, angle); - votes[ind] = make_int3(curVotes, scaleVotes, angleVotes); - } - } - } - - int GHT_Guil_Full_findPosInHist_gpu(PtrStepSzi hist, float4* out, int3* votes, int curSize, int maxSize, - float angle, int angleVotes, float scale, int scaleVotes, - float dp, int threshold) - { - void* counterPtr; - cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); - - cudaSafeCall( cudaMemcpy(counterPtr, &curSize, sizeof(int), cudaMemcpyHostToDevice) ); - - const dim3 block(32, 8); - const dim3 grid(divUp(hist.cols - 2, block.x), divUp(hist.rows - 2, block.y)); - - cudaSafeCall( cudaFuncSetCacheConfig(GHT_Guil_Full_findPosInHist, cudaFuncCachePreferL1) ); - - GHT_Guil_Full_findPosInHist<<>>(hist, out, votes, maxSize, - angle, angleVotes, scale, scaleVotes, - dp, threshold); - cudaSafeCall( cudaGetLastError() ); - - cudaSafeCall( cudaDeviceSynchronize() ); - - int totalCount; - cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); - - totalCount = ::min(totalCount, maxSize); - - return totalCount; - } - } -}}} - - -#endif /* CUDA_DISABLER */ diff --git a/modules/gpuimgproc/src/cuda/hough_circles.cu b/modules/gpuimgproc/src/cuda/hough_circles.cu new file mode 100644 index 000000000..6757e430b --- /dev/null +++ b/modules/gpuimgproc/src/cuda/hough_circles.cu @@ -0,0 +1,260 @@ +/*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/core/cuda/common.hpp" +#include "opencv2/core/cuda/emulation.hpp" +#include "opencv2/core/cuda/dynamic_smem.hpp" + +#include "opencv2/opencv_modules.hpp" + +#ifdef HAVE_OPENCV_GPUFILTERS + +namespace cv { namespace gpu { namespace cudev +{ + namespace hough_circles + { + __device__ int g_counter; + + //////////////////////////////////////////////////////////////////////// + // circlesAccumCenters + + __global__ void circlesAccumCenters(const unsigned int* list, const int count, const PtrStepi dx, const PtrStepi dy, + PtrStepi accum, const int width, const int height, const int minRadius, const int maxRadius, const float idp) + { + const int SHIFT = 10; + const int ONE = 1 << SHIFT; + + const int tid = blockIdx.x * blockDim.x + threadIdx.x; + + if (tid >= count) + return; + + const unsigned int val = list[tid]; + + const int x = (val & 0xFFFF); + const int y = (val >> 16) & 0xFFFF; + + const int vx = dx(y, x); + const int vy = dy(y, x); + + if (vx == 0 && vy == 0) + return; + + const float mag = ::sqrtf(vx * vx + vy * vy); + + const int x0 = __float2int_rn((x * idp) * ONE); + const int y0 = __float2int_rn((y * idp) * ONE); + + int sx = __float2int_rn((vx * idp) * ONE / mag); + int sy = __float2int_rn((vy * idp) * ONE / mag); + + // Step from minRadius to maxRadius in both directions of the gradient + for (int k1 = 0; k1 < 2; ++k1) + { + int x1 = x0 + minRadius * sx; + int y1 = y0 + minRadius * sy; + + for (int r = minRadius; r <= maxRadius; x1 += sx, y1 += sy, ++r) + { + const int x2 = x1 >> SHIFT; + const int y2 = y1 >> SHIFT; + + if (x2 < 0 || x2 >= width || y2 < 0 || y2 >= height) + break; + + ::atomicAdd(accum.ptr(y2 + 1) + x2 + 1, 1); + } + + sx = -sx; + sy = -sy; + } + } + + void circlesAccumCenters_gpu(const unsigned int* list, int count, PtrStepi dx, PtrStepi dy, PtrStepSzi accum, int minRadius, int maxRadius, float idp) + { + const dim3 block(256); + const dim3 grid(divUp(count, block.x)); + + cudaSafeCall( cudaFuncSetCacheConfig(circlesAccumCenters, cudaFuncCachePreferL1) ); + + circlesAccumCenters<<>>(list, count, dx, dy, accum, accum.cols - 2, accum.rows - 2, minRadius, maxRadius, idp); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + } + + //////////////////////////////////////////////////////////////////////// + // buildCentersList + + __global__ void buildCentersList(const PtrStepSzi accum, unsigned int* centers, const int threshold) + { + const int x = blockIdx.x * blockDim.x + threadIdx.x; + const int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x < accum.cols - 2 && y < accum.rows - 2) + { + const int top = accum(y, x + 1); + + const int left = accum(y + 1, x); + const int cur = accum(y + 1, x + 1); + const int right = accum(y + 1, x + 2); + + const int bottom = accum(y + 2, x + 1); + + if (cur > threshold && cur > top && cur >= bottom && cur > left && cur >= right) + { + const unsigned int val = (y << 16) | x; + const int idx = ::atomicAdd(&g_counter, 1); + centers[idx] = val; + } + } + } + + int buildCentersList_gpu(PtrStepSzi accum, unsigned int* centers, int threshold) + { + void* counterPtr; + cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); + + cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); + + const dim3 block(32, 8); + const dim3 grid(divUp(accum.cols - 2, block.x), divUp(accum.rows - 2, block.y)); + + cudaSafeCall( cudaFuncSetCacheConfig(buildCentersList, cudaFuncCachePreferL1) ); + + buildCentersList<<>>(accum, centers, threshold); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + int totalCount; + cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); + + return totalCount; + } + + //////////////////////////////////////////////////////////////////////// + // circlesAccumRadius + + __global__ void circlesAccumRadius(const unsigned int* centers, const unsigned int* list, const int count, + float3* circles, const int maxCircles, const float dp, + const int minRadius, const int maxRadius, const int histSize, const int threshold) + { + int* smem = DynamicSharedMem(); + + for (int i = threadIdx.x; i < histSize + 2; i += blockDim.x) + smem[i] = 0; + __syncthreads(); + + unsigned int val = centers[blockIdx.x]; + + float cx = (val & 0xFFFF); + float cy = (val >> 16) & 0xFFFF; + + cx = (cx + 0.5f) * dp; + cy = (cy + 0.5f) * dp; + + for (int i = threadIdx.x; i < count; i += blockDim.x) + { + val = list[i]; + + const int x = (val & 0xFFFF); + const int y = (val >> 16) & 0xFFFF; + + const float rad = ::sqrtf((cx - x) * (cx - x) + (cy - y) * (cy - y)); + if (rad >= minRadius && rad <= maxRadius) + { + const int r = __float2int_rn(rad - minRadius); + + Emulation::smem::atomicAdd(&smem[r + 1], 1); + } + } + + __syncthreads(); + + for (int i = threadIdx.x; i < histSize; i += blockDim.x) + { + const int curVotes = smem[i + 1]; + + if (curVotes >= threshold && curVotes > smem[i] && curVotes >= smem[i + 2]) + { + const int ind = ::atomicAdd(&g_counter, 1); + if (ind < maxCircles) + circles[ind] = make_float3(cx, cy, i + minRadius); + } + } + } + + int circlesAccumRadius_gpu(const unsigned int* centers, int centersCount, const unsigned int* list, int count, + float3* circles, int maxCircles, float dp, int minRadius, int maxRadius, int threshold, bool has20) + { + void* counterPtr; + cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); + + cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); + + const dim3 block(has20 ? 1024 : 512); + const dim3 grid(centersCount); + + const int histSize = maxRadius - minRadius + 1; + size_t smemSize = (histSize + 2) * sizeof(int); + + circlesAccumRadius<<>>(centers, list, count, circles, maxCircles, dp, minRadius, maxRadius, histSize, threshold); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + int totalCount; + cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); + + totalCount = ::min(totalCount, maxCircles); + + return totalCount; + } + } +}}} + +#endif // HAVE_OPENCV_GPUFILTERS + +#endif /* CUDA_DISABLER */ diff --git a/modules/gpuimgproc/src/cuda/hough_lines.cu b/modules/gpuimgproc/src/cuda/hough_lines.cu new file mode 100644 index 000000000..0cee0a43d --- /dev/null +++ b/modules/gpuimgproc/src/cuda/hough_lines.cu @@ -0,0 +1,212 @@ +/*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 "opencv2/core/cuda/common.hpp" +#include "opencv2/core/cuda/emulation.hpp" +#include "opencv2/core/cuda/dynamic_smem.hpp" + +namespace cv { namespace gpu { namespace cudev +{ + namespace hough_lines + { + __device__ int g_counter; + + //////////////////////////////////////////////////////////////////////// + // linesAccum + + __global__ void linesAccumGlobal(const unsigned int* list, const int count, PtrStepi accum, const float irho, const float theta, const int numrho) + { + const int n = blockIdx.x; + const float ang = n * theta; + + float sinVal; + float cosVal; + sincosf(ang, &sinVal, &cosVal); + sinVal *= irho; + cosVal *= irho; + + const int shift = (numrho - 1) / 2; + + int* accumRow = accum.ptr(n + 1); + for (int i = threadIdx.x; i < count; i += blockDim.x) + { + const unsigned int val = list[i]; + + const int x = (val & 0xFFFF); + const int y = (val >> 16) & 0xFFFF; + + int r = __float2int_rn(x * cosVal + y * sinVal); + r += shift; + + ::atomicAdd(accumRow + r + 1, 1); + } + } + + __global__ void linesAccumShared(const unsigned int* list, const int count, PtrStepi accum, const float irho, const float theta, const int numrho) + { + int* smem = DynamicSharedMem(); + + for (int i = threadIdx.x; i < numrho + 1; i += blockDim.x) + smem[i] = 0; + + __syncthreads(); + + const int n = blockIdx.x; + const float ang = n * theta; + + float sinVal; + float cosVal; + sincosf(ang, &sinVal, &cosVal); + sinVal *= irho; + cosVal *= irho; + + const int shift = (numrho - 1) / 2; + + for (int i = threadIdx.x; i < count; i += blockDim.x) + { + const unsigned int val = list[i]; + + const int x = (val & 0xFFFF); + const int y = (val >> 16) & 0xFFFF; + + int r = __float2int_rn(x * cosVal + y * sinVal); + r += shift; + + Emulation::smem::atomicAdd(&smem[r + 1], 1); + } + + __syncthreads(); + + int* accumRow = accum.ptr(n + 1); + for (int i = threadIdx.x; i < numrho + 1; i += blockDim.x) + accumRow[i] = smem[i]; + } + + void linesAccum_gpu(const unsigned int* list, int count, PtrStepSzi accum, float rho, float theta, size_t sharedMemPerBlock, bool has20) + { + const dim3 block(has20 ? 1024 : 512); + const dim3 grid(accum.rows - 2); + + size_t smemSize = (accum.cols - 1) * sizeof(int); + + if (smemSize < sharedMemPerBlock - 1000) + linesAccumShared<<>>(list, count, accum, 1.0f / rho, theta, accum.cols - 2); + else + linesAccumGlobal<<>>(list, count, accum, 1.0f / rho, theta, accum.cols - 2); + + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + } + + //////////////////////////////////////////////////////////////////////// + // linesGetResult + + __global__ void linesGetResult(const PtrStepSzi accum, float2* out, int* votes, const int maxSize, const float rho, const float theta, const int threshold, const int numrho) + { + const int r = blockIdx.x * blockDim.x + threadIdx.x; + const int n = blockIdx.y * blockDim.y + threadIdx.y; + + if (r >= accum.cols - 2 || n >= accum.rows - 2) + return; + + const int curVotes = accum(n + 1, r + 1); + + if (curVotes > threshold && + curVotes > accum(n + 1, r) && + curVotes >= accum(n + 1, r + 2) && + curVotes > accum(n, r + 1) && + curVotes >= accum(n + 2, r + 1)) + { + const float radius = (r - (numrho - 1) * 0.5f) * rho; + const float angle = n * theta; + + const int ind = ::atomicAdd(&g_counter, 1); + if (ind < maxSize) + { + out[ind] = make_float2(radius, angle); + votes[ind] = curVotes; + } + } + } + + int linesGetResult_gpu(PtrStepSzi accum, float2* out, int* votes, int maxSize, float rho, float theta, int threshold, bool doSort) + { + void* counterPtr; + cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); + + cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); + + const dim3 block(32, 8); + const dim3 grid(divUp(accum.cols - 2, block.x), divUp(accum.rows - 2, block.y)); + + cudaSafeCall( cudaFuncSetCacheConfig(linesGetResult, cudaFuncCachePreferL1) ); + + linesGetResult<<>>(accum, out, votes, maxSize, rho, theta, threshold, accum.cols - 2); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + int totalCount; + cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); + + totalCount = ::min(totalCount, maxSize); + + if (doSort && totalCount > 0) + { + thrust::device_ptr outPtr(out); + thrust::device_ptr votesPtr(votes); + thrust::sort_by_key(votesPtr, votesPtr + totalCount, outPtr, thrust::greater()); + } + + return totalCount; + } + } +}}} + + +#endif /* CUDA_DISABLER */ diff --git a/modules/gpuimgproc/src/cuda/hough_segments.cu b/modules/gpuimgproc/src/cuda/hough_segments.cu new file mode 100644 index 000000000..e420449fa --- /dev/null +++ b/modules/gpuimgproc/src/cuda/hough_segments.cu @@ -0,0 +1,249 @@ +/*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/core/cuda/common.hpp" +#include "opencv2/core/cuda/vec_math.hpp" + +namespace cv { namespace gpu { namespace cudev +{ + namespace hough_segments + { + __device__ int g_counter; + + texture tex_mask(false, cudaFilterModePoint, cudaAddressModeClamp); + + __global__ void houghLinesProbabilistic(const PtrStepSzi accum, + int4* out, const int maxSize, + const float rho, const float theta, + const int lineGap, const int lineLength, + const int rows, const int cols) + { + const int r = blockIdx.x * blockDim.x + threadIdx.x; + const int n = blockIdx.y * blockDim.y + threadIdx.y; + + if (r >= accum.cols - 2 || n >= accum.rows - 2) + return; + + const int curVotes = accum(n + 1, r + 1); + + if (curVotes >= lineLength && + curVotes > accum(n, r) && + curVotes > accum(n, r + 1) && + curVotes > accum(n, r + 2) && + curVotes > accum(n + 1, r) && + curVotes > accum(n + 1, r + 2) && + curVotes > accum(n + 2, r) && + curVotes > accum(n + 2, r + 1) && + curVotes > accum(n + 2, r + 2)) + { + const float radius = (r - (accum.cols - 2 - 1) * 0.5f) * rho; + const float angle = n * theta; + + float cosa; + float sina; + sincosf(angle, &sina, &cosa); + + float2 p0 = make_float2(cosa * radius, sina * radius); + float2 dir = make_float2(-sina, cosa); + + float2 pb[4] = {make_float2(-1, -1), make_float2(-1, -1), make_float2(-1, -1), make_float2(-1, -1)}; + float a; + + if (dir.x != 0) + { + a = -p0.x / dir.x; + pb[0].x = 0; + pb[0].y = p0.y + a * dir.y; + + a = (cols - 1 - p0.x) / dir.x; + pb[1].x = cols - 1; + pb[1].y = p0.y + a * dir.y; + } + if (dir.y != 0) + { + a = -p0.y / dir.y; + pb[2].x = p0.x + a * dir.x; + pb[2].y = 0; + + a = (rows - 1 - p0.y) / dir.y; + pb[3].x = p0.x + a * dir.x; + pb[3].y = rows - 1; + } + + if (pb[0].x == 0 && (pb[0].y >= 0 && pb[0].y < rows)) + { + p0 = pb[0]; + if (dir.x < 0) + dir = -dir; + } + else if (pb[1].x == cols - 1 && (pb[0].y >= 0 && pb[0].y < rows)) + { + p0 = pb[1]; + if (dir.x > 0) + dir = -dir; + } + else if (pb[2].y == 0 && (pb[2].x >= 0 && pb[2].x < cols)) + { + p0 = pb[2]; + if (dir.y < 0) + dir = -dir; + } + else if (pb[3].y == rows - 1 && (pb[3].x >= 0 && pb[3].x < cols)) + { + p0 = pb[3]; + if (dir.y > 0) + dir = -dir; + } + + float2 d; + if (::fabsf(dir.x) > ::fabsf(dir.y)) + { + d.x = dir.x > 0 ? 1 : -1; + d.y = dir.y / ::fabsf(dir.x); + } + else + { + d.x = dir.x / ::fabsf(dir.y); + d.y = dir.y > 0 ? 1 : -1; + } + + float2 line_end[2]; + int gap; + bool inLine = false; + + float2 p1 = p0; + if (p1.x < 0 || p1.x >= cols || p1.y < 0 || p1.y >= rows) + return; + + for (;;) + { + if (tex2D(tex_mask, p1.x, p1.y)) + { + gap = 0; + + if (!inLine) + { + line_end[0] = p1; + line_end[1] = p1; + inLine = true; + } + else + { + line_end[1] = p1; + } + } + else if (inLine) + { + if (++gap > lineGap) + { + bool good_line = ::abs(line_end[1].x - line_end[0].x) >= lineLength || + ::abs(line_end[1].y - line_end[0].y) >= lineLength; + + if (good_line) + { + const int ind = ::atomicAdd(&g_counter, 1); + if (ind < maxSize) + out[ind] = make_int4(line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y); + } + + gap = 0; + inLine = false; + } + } + + p1 = p1 + d; + if (p1.x < 0 || p1.x >= cols || p1.y < 0 || p1.y >= rows) + { + if (inLine) + { + bool good_line = ::abs(line_end[1].x - line_end[0].x) >= lineLength || + ::abs(line_end[1].y - line_end[0].y) >= lineLength; + + if (good_line) + { + const int ind = ::atomicAdd(&g_counter, 1); + if (ind < maxSize) + out[ind] = make_int4(line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y); + } + + } + break; + } + } + } + } + + int houghLinesProbabilistic_gpu(PtrStepSzb mask, PtrStepSzi accum, int4* out, int maxSize, float rho, float theta, int lineGap, int lineLength) + { + void* counterPtr; + cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) ); + + cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) ); + + const dim3 block(32, 8); + const dim3 grid(divUp(accum.cols - 2, block.x), divUp(accum.rows - 2, block.y)); + + bindTexture(&tex_mask, mask); + + houghLinesProbabilistic<<>>(accum, + out, maxSize, + rho, theta, + lineGap, lineLength, + mask.rows, mask.cols); + cudaSafeCall( cudaGetLastError() ); + + cudaSafeCall( cudaDeviceSynchronize() ); + + int totalCount; + cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) ); + + totalCount = ::min(totalCount, maxSize); + + return totalCount; + } + } +}}} + + +#endif /* CUDA_DISABLER */ diff --git a/modules/gpuimgproc/src/generalized_hough.cpp b/modules/gpuimgproc/src/generalized_hough.cpp new file mode 100644 index 000000000..abcd3ef49 --- /dev/null +++ b/modules/gpuimgproc/src/generalized_hough.cpp @@ -0,0 +1,906 @@ +/*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; + +#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) || !defined(HAVE_OPENCV_GPUARITHM) + +Ptr cv::gpu::createGeneralizedHoughBallard() { throw_no_cuda(); return Ptr(); } + +Ptr cv::gpu::createGeneralizedHoughGuil() { throw_no_cuda(); return Ptr(); } + +#else /* !defined (HAVE_CUDA) */ + +namespace cv { namespace gpu { namespace cudev +{ + namespace ght + { + template + int buildEdgePointList_gpu(PtrStepSzb edges, PtrStepSzb dx, PtrStepSzb dy, unsigned int* coordList, float* thetaList); + void buildRTable_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, + PtrStepSz r_table, int* r_sizes, + short2 templCenter, int levels); + + void Ballard_Pos_calcHist_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, + PtrStepSz r_table, const int* r_sizes, + PtrStepSzi hist, + float dp, int levels); + int Ballard_Pos_findPosInHist_gpu(PtrStepSzi hist, float4* out, int3* votes, int maxSize, float dp, int threshold); + + void Guil_Full_setTemplFeatures(PtrStepb p1_pos, PtrStepb p1_theta, PtrStepb p2_pos, PtrStepb d12, PtrStepb r1, PtrStepb r2); + void Guil_Full_setImageFeatures(PtrStepb p1_pos, PtrStepb p1_theta, PtrStepb p2_pos, PtrStepb d12, PtrStepb r1, PtrStepb r2); + void Guil_Full_buildTemplFeatureList_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, + int* sizes, int maxSize, + float xi, float angleEpsilon, int levels, + float2 center, float maxDist); + void Guil_Full_buildImageFeatureList_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, + int* sizes, int maxSize, + float xi, float angleEpsilon, int levels, + float2 center, float maxDist); + void Guil_Full_calcOHist_gpu(const int* templSizes, const int* imageSizes, int* OHist, + float minAngle, float maxAngle, float angleStep, int angleRange, + int levels, int tMaxSize); + void Guil_Full_calcSHist_gpu(const int* templSizes, const int* imageSizes, int* SHist, + float angle, float angleEpsilon, + float minScale, float maxScale, float iScaleStep, int scaleRange, + int levels, int tMaxSize); + void Guil_Full_calcPHist_gpu(const int* templSizes, const int* imageSizes, PtrStepSzi PHist, + float angle, float angleEpsilon, float scale, + float dp, + int levels, int tMaxSize); + int Guil_Full_findPosInHist_gpu(PtrStepSzi hist, float4* out, int3* votes, int curSize, int maxSize, + float angle, int angleVotes, float scale, int scaleVotes, + float dp, int threshold); + } +}}} + +// common + +namespace +{ + class GeneralizedHoughBase + { + protected: + GeneralizedHoughBase(); + virtual ~GeneralizedHoughBase() {} + + void setTemplateImpl(InputArray templ, Point templCenter); + void setTemplateImpl(InputArray edges, InputArray dx, InputArray dy, Point templCenter); + + void detectImpl(InputArray image, OutputArray positions, OutputArray votes); + void detectImpl(InputArray edges, InputArray dx, InputArray dy, OutputArray positions, OutputArray votes); + + void buildEdgePointList(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy); + + virtual void processTempl() = 0; + virtual void processImage() = 0; + + int cannyLowThresh_; + int cannyHighThresh_; + double minDist_; + double dp_; + int maxBufferSize_; + + Size templSize_; + Point templCenter_; + GpuMat templEdges_; + GpuMat templDx_; + GpuMat templDy_; + + Size imageSize_; + GpuMat imageEdges_; + GpuMat imageDx_; + GpuMat imageDy_; + + GpuMat edgePointList_; + + GpuMat outBuf_; + int posCount_; + + private: +#ifdef HAVE_OPENCV_GPUFILTERS + void calcEdges(InputArray src, GpuMat& edges, GpuMat& dx, GpuMat& dy); +#endif + + void filterMinDist(); + void convertTo(OutputArray positions, OutputArray votes); + +#ifdef HAVE_OPENCV_GPUFILTERS + Ptr canny_; + Ptr filterDx_; + Ptr filterDy_; +#endif + + std::vector oldPosBuf_; + std::vector oldVoteBuf_; + std::vector newPosBuf_; + std::vector newVoteBuf_; + std::vector indexies_; + }; + + GeneralizedHoughBase::GeneralizedHoughBase() + { + cannyLowThresh_ = 50; + cannyHighThresh_ = 100; + minDist_ = 1.0; + dp_ = 1.0; + + maxBufferSize_ = 10000; + +#ifdef HAVE_OPENCV_GPUFILTERS + canny_ = gpu::createCannyEdgeDetector(cannyLowThresh_, cannyHighThresh_); + filterDx_ = gpu::createSobelFilter(CV_8UC1, CV_32S, 1, 0); + filterDy_ = gpu::createSobelFilter(CV_8UC1, CV_32S, 0, 1); +#endif + } + +#ifdef HAVE_OPENCV_GPUFILTERS + void GeneralizedHoughBase::calcEdges(InputArray _src, GpuMat& edges, GpuMat& dx, GpuMat& dy) + { + GpuMat src = _src.getGpuMat(); + + CV_Assert( src.type() == CV_8UC1 ); + CV_Assert( cannyLowThresh_ > 0 && cannyLowThresh_ < cannyHighThresh_ ); + + ensureSizeIsEnough(src.size(), CV_32SC1, dx); + ensureSizeIsEnough(src.size(), CV_32SC1, dy); + + filterDx_->apply(src, dx); + filterDy_->apply(src, dy); + + ensureSizeIsEnough(src.size(), CV_8UC1, edges); + + canny_->setLowThreshold(cannyLowThresh_); + canny_->setHighThreshold(cannyHighThresh_); + canny_->detect(dx, dy, edges); + } +#endif + + void GeneralizedHoughBase::setTemplateImpl(InputArray templ, Point templCenter) + { +#ifndef HAVE_OPENCV_GPUFILTERS + (void) templ; + (void) templCenter; + throw_no_cuda(); +#else + calcEdges(templ, templEdges_, templDx_, templDy_); + + if (templCenter == Point(-1, -1)) + templCenter = Point(templEdges_.cols / 2, templEdges_.rows / 2); + + templSize_ = templEdges_.size(); + templCenter_ = templCenter; + + processTempl(); +#endif + } + + void GeneralizedHoughBase::setTemplateImpl(InputArray edges, InputArray dx, InputArray dy, Point templCenter) + { + edges.getGpuMat().copyTo(templEdges_); + dx.getGpuMat().copyTo(templDx_); + dy.getGpuMat().copyTo(templDy_); + + CV_Assert( templEdges_.type() == CV_8UC1 ); + CV_Assert( templDx_.type() == CV_32FC1 && templDx_.size() == templEdges_.size() ); + CV_Assert( templDy_.type() == templDx_.type() && templDy_.size() == templEdges_.size() ); + + if (templCenter == Point(-1, -1)) + templCenter = Point(templEdges_.cols / 2, templEdges_.rows / 2); + + templSize_ = templEdges_.size(); + templCenter_ = templCenter; + + processTempl(); + } + + void GeneralizedHoughBase::detectImpl(InputArray image, OutputArray positions, OutputArray votes) + { +#ifndef HAVE_OPENCV_GPUFILTERS + (void) templ; + (void) templCenter; + throw_no_cuda(); +#else + calcEdges(image, imageEdges_, imageDx_, imageDy_); + + imageSize_ = imageEdges_.size(); + + posCount_ = 0; + + processImage(); + + if (posCount_ == 0) + { + positions.release(); + if (votes.needed()) + votes.release(); + } + else + { + if (minDist_ > 1) + filterMinDist(); + convertTo(positions, votes); + } +#endif + } + + void GeneralizedHoughBase::detectImpl(InputArray edges, InputArray dx, InputArray dy, OutputArray positions, OutputArray votes) + { + edges.getGpuMat().copyTo(imageEdges_); + dx.getGpuMat().copyTo(imageDx_); + dy.getGpuMat().copyTo(imageDy_); + + CV_Assert( imageEdges_.type() == CV_8UC1 ); + CV_Assert( imageDx_.type() == CV_32FC1 && imageDx_.size() == imageEdges_.size() ); + CV_Assert( imageDy_.type() == imageDx_.type() && imageDy_.size() == imageEdges_.size() ); + + imageSize_ = imageEdges_.size(); + + posCount_ = 0; + + processImage(); + + if (posCount_ == 0) + { + positions.release(); + if (votes.needed()) + votes.release(); + } + else + { + if (minDist_ > 1) + filterMinDist(); + convertTo(positions, votes); + } + } + + void GeneralizedHoughBase::buildEdgePointList(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy) + { + using namespace cv::gpu::cudev::ght; + + typedef int (*func_t)(PtrStepSzb edges, PtrStepSzb dx, PtrStepSzb dy, unsigned int* coordList, float* thetaList); + static const func_t funcs[] = + { + 0, + 0, + 0, + buildEdgePointList_gpu, + buildEdgePointList_gpu, + buildEdgePointList_gpu, + 0 + }; + + CV_Assert( edges.type() == CV_8UC1 ); + CV_Assert( dx.size() == edges.size() ); + CV_Assert( dy.type() == dx.type() && dy.size() == edges.size() ); + + const func_t func = funcs[dx.depth()]; + CV_Assert( func != 0 ); + + edgePointList_.cols = (int) (edgePointList_.step / sizeof(int)); + ensureSizeIsEnough(2, edges.size().area(), CV_32SC1, edgePointList_); + + edgePointList_.cols = func(edges, dx, dy, edgePointList_.ptr(0), edgePointList_.ptr(1)); + } + + struct IndexCmp + { + const int3* aux; + + explicit IndexCmp(const int3* _aux) : aux(_aux) {} + + bool operator ()(int l1, int l2) const + { + return aux[l1].x > aux[l2].x; + } + }; + + void GeneralizedHoughBase::filterMinDist() + { + oldPosBuf_.resize(posCount_); + oldVoteBuf_.resize(posCount_); + + cudaSafeCall( cudaMemcpy(&oldPosBuf_[0], outBuf_.ptr(0), posCount_ * sizeof(float4), cudaMemcpyDeviceToHost) ); + cudaSafeCall( cudaMemcpy(&oldVoteBuf_[0], outBuf_.ptr(1), posCount_ * sizeof(int3), cudaMemcpyDeviceToHost) ); + + indexies_.resize(posCount_); + for (int i = 0; i < posCount_; ++i) + indexies_[i] = i; + std::sort(indexies_.begin(), indexies_.end(), IndexCmp(&oldVoteBuf_[0])); + + newPosBuf_.clear(); + newVoteBuf_.clear(); + newPosBuf_.reserve(posCount_); + newVoteBuf_.reserve(posCount_); + + const int cellSize = cvRound(minDist_); + const int gridWidth = (imageSize_.width + cellSize - 1) / cellSize; + const int gridHeight = (imageSize_.height + cellSize - 1) / cellSize; + + std::vector< std::vector > grid(gridWidth * gridHeight); + + const double minDist2 = minDist_ * minDist_; + + for (int i = 0; i < posCount_; ++i) + { + const int ind = indexies_[i]; + + Point2f p(oldPosBuf_[ind].x, oldPosBuf_[ind].y); + + bool good = true; + + const int xCell = static_cast(p.x / cellSize); + const int yCell = static_cast(p.y / cellSize); + + int x1 = xCell - 1; + int y1 = yCell - 1; + int x2 = xCell + 1; + int y2 = yCell + 1; + + // boundary check + x1 = std::max(0, x1); + y1 = std::max(0, y1); + x2 = std::min(gridWidth - 1, x2); + y2 = std::min(gridHeight - 1, y2); + + for (int yy = y1; yy <= y2; ++yy) + { + for (int xx = x1; xx <= x2; ++xx) + { + const std::vector& m = grid[yy * gridWidth + xx]; + + for(size_t j = 0; j < m.size(); ++j) + { + const Point2f d = p - m[j]; + + if (d.ddot(d) < minDist2) + { + good = false; + goto break_out; + } + } + } + } + + break_out: + + if(good) + { + grid[yCell * gridWidth + xCell].push_back(p); + + newPosBuf_.push_back(oldPosBuf_[ind]); + newVoteBuf_.push_back(oldVoteBuf_[ind]); + } + } + + posCount_ = static_cast(newPosBuf_.size()); + cudaSafeCall( cudaMemcpy(outBuf_.ptr(0), &newPosBuf_[0], posCount_ * sizeof(float4), cudaMemcpyHostToDevice) ); + cudaSafeCall( cudaMemcpy(outBuf_.ptr(1), &newVoteBuf_[0], posCount_ * sizeof(int3), cudaMemcpyHostToDevice) ); + } + + void GeneralizedHoughBase::convertTo(OutputArray positions, OutputArray votes) + { + ensureSizeIsEnough(1, posCount_, CV_32FC4, positions); + GpuMat(1, posCount_, CV_32FC4, outBuf_.ptr(0), outBuf_.step).copyTo(positions); + + if (votes.needed()) + { + ensureSizeIsEnough(1, posCount_, CV_32FC3, votes); + GpuMat(1, posCount_, CV_32FC4, outBuf_.ptr(1), outBuf_.step).copyTo(votes); + } + } +} + +// GeneralizedHoughBallard + +namespace +{ + class GeneralizedHoughBallardImpl : public GeneralizedHoughBallard, private GeneralizedHoughBase + { + public: + GeneralizedHoughBallardImpl(); + + void setTemplate(InputArray templ, Point templCenter) { setTemplateImpl(templ, templCenter); } + void setTemplate(InputArray edges, InputArray dx, InputArray dy, Point templCenter) { setTemplateImpl(edges, dx, dy, templCenter); } + + void detect(InputArray image, OutputArray positions, OutputArray votes) { detectImpl(image, positions, votes); } + void detect(InputArray edges, InputArray dx, InputArray dy, OutputArray positions, OutputArray votes) { detectImpl(edges, dx, dy, positions, votes); } + + void setCannyLowThresh(int cannyLowThresh) { cannyLowThresh_ = cannyLowThresh; } + int getCannyLowThresh() const { return cannyLowThresh_; } + + void setCannyHighThresh(int cannyHighThresh) { cannyHighThresh_ = cannyHighThresh; } + int getCannyHighThresh() const { return cannyHighThresh_; } + + void setMinDist(double minDist) { minDist_ = minDist; } + double getMinDist() const { return minDist_; } + + void setDp(double dp) { dp_ = dp; } + double getDp() const { return dp_; } + + void setMaxBufferSize(int maxBufferSize) { maxBufferSize_ = maxBufferSize; } + int getMaxBufferSize() const { return maxBufferSize_; } + + void setLevels(int levels) { levels_ = levels; } + int getLevels() const { return levels_; } + + void setVotesThreshold(int votesThreshold) { votesThreshold_ = votesThreshold; } + int getVotesThreshold() const { return votesThreshold_; } + + private: + void processTempl(); + void processImage(); + + void calcHist(); + void findPosInHist(); + + int levels_; + int votesThreshold_; + + GpuMat r_table_; + GpuMat r_sizes_; + + GpuMat hist_; + }; + + GeneralizedHoughBallardImpl::GeneralizedHoughBallardImpl() + { + levels_ = 360; + votesThreshold_ = 100; + } + + void GeneralizedHoughBallardImpl::processTempl() + { + using namespace cv::gpu::cudev::ght; + + CV_Assert( levels_ > 0 ); + + buildEdgePointList(templEdges_, templDx_, templDy_); + + ensureSizeIsEnough(levels_ + 1, maxBufferSize_, CV_16SC2, r_table_); + ensureSizeIsEnough(1, levels_ + 1, CV_32SC1, r_sizes_); + r_sizes_.setTo(Scalar::all(0)); + + if (edgePointList_.cols > 0) + { + buildRTable_gpu(edgePointList_.ptr(0), edgePointList_.ptr(1), edgePointList_.cols, + r_table_, r_sizes_.ptr(), make_short2(templCenter_.x, templCenter_.y), levels_); + gpu::min(r_sizes_, maxBufferSize_, r_sizes_); + } + } + + void GeneralizedHoughBallardImpl::processImage() + { + calcHist(); + findPosInHist(); + } + + void GeneralizedHoughBallardImpl::calcHist() + { + using namespace cv::gpu::cudev::ght; + + CV_Assert( levels_ > 0 && r_table_.rows == (levels_ + 1) && r_sizes_.cols == (levels_ + 1) ); + CV_Assert( dp_ > 0.0); + + const double idp = 1.0 / dp_; + + buildEdgePointList(imageEdges_, imageDx_, imageDy_); + + ensureSizeIsEnough(cvCeil(imageSize_.height * idp) + 2, cvCeil(imageSize_.width * idp) + 2, CV_32SC1, hist_); + hist_.setTo(Scalar::all(0)); + + if (edgePointList_.cols > 0) + { + Ballard_Pos_calcHist_gpu(edgePointList_.ptr(0), edgePointList_.ptr(1), edgePointList_.cols, + r_table_, r_sizes_.ptr(), + hist_, + (float)dp_, levels_); + } + } + + void GeneralizedHoughBallardImpl::findPosInHist() + { + using namespace cv::gpu::cudev::ght; + + CV_Assert( votesThreshold_ > 0 ); + + ensureSizeIsEnough(2, maxBufferSize_, CV_32FC4, outBuf_); + + posCount_ = Ballard_Pos_findPosInHist_gpu(hist_, outBuf_.ptr(0), outBuf_.ptr(1), maxBufferSize_, (float)dp_, votesThreshold_); + } +} + +Ptr cv::gpu::createGeneralizedHoughBallard() +{ + return makePtr(); +} + +// GeneralizedHoughGuil + +namespace +{ + class GeneralizedHoughGuilImpl : public GeneralizedHoughGuil, private GeneralizedHoughBase + { + public: + GeneralizedHoughGuilImpl(); + + void setTemplate(InputArray templ, Point templCenter) { setTemplateImpl(templ, templCenter); } + void setTemplate(InputArray edges, InputArray dx, InputArray dy, Point templCenter) { setTemplateImpl(edges, dx, dy, templCenter); } + + void detect(InputArray image, OutputArray positions, OutputArray votes) { detectImpl(image, positions, votes); } + void detect(InputArray edges, InputArray dx, InputArray dy, OutputArray positions, OutputArray votes) { detectImpl(edges, dx, dy, positions, votes); } + + void setCannyLowThresh(int cannyLowThresh) { cannyLowThresh_ = cannyLowThresh; } + int getCannyLowThresh() const { return cannyLowThresh_; } + + void setCannyHighThresh(int cannyHighThresh) { cannyHighThresh_ = cannyHighThresh; } + int getCannyHighThresh() const { return cannyHighThresh_; } + + void setMinDist(double minDist) { minDist_ = minDist; } + double getMinDist() const { return minDist_; } + + void setDp(double dp) { dp_ = dp; } + double getDp() const { return dp_; } + + void setMaxBufferSize(int maxBufferSize) { maxBufferSize_ = maxBufferSize; } + int getMaxBufferSize() const { return maxBufferSize_; } + + void setXi(double xi) { xi_ = xi; } + double getXi() const { return xi_; } + + void setLevels(int levels) { levels_ = levels; } + int getLevels() const { return levels_; } + + void setAngleEpsilon(double angleEpsilon) { angleEpsilon_ = angleEpsilon; } + double getAngleEpsilon() const { return angleEpsilon_; } + + void setMinAngle(double minAngle) { minAngle_ = minAngle; } + double getMinAngle() const { return minAngle_; } + + void setMaxAngle(double maxAngle) { maxAngle_ = maxAngle; } + double getMaxAngle() const { return maxAngle_; } + + void setAngleStep(double angleStep) { angleStep_ = angleStep; } + double getAngleStep() const { return angleStep_; } + + void setAngleThresh(int angleThresh) { angleThresh_ = angleThresh; } + int getAngleThresh() const { return angleThresh_; } + + void setMinScale(double minScale) { minScale_ = minScale; } + double getMinScale() const { return minScale_; } + + void setMaxScale(double maxScale) { maxScale_ = maxScale; } + double getMaxScale() const { return maxScale_; } + + void setScaleStep(double scaleStep) { scaleStep_ = scaleStep; } + double getScaleStep() const { return scaleStep_; } + + void setScaleThresh(int scaleThresh) { scaleThresh_ = scaleThresh; } + int getScaleThresh() const { return scaleThresh_; } + + void setPosThresh(int posThresh) { posThresh_ = posThresh; } + int getPosThresh() const { return posThresh_; } + + private: + void processTempl(); + void processImage(); + + double xi_; + int levels_; + double angleEpsilon_; + + double minAngle_; + double maxAngle_; + double angleStep_; + int angleThresh_; + + double minScale_; + double maxScale_; + double scaleStep_; + int scaleThresh_; + + int posThresh_; + + struct Feature + { + GpuMat p1_pos; + GpuMat p1_theta; + GpuMat p2_pos; + + GpuMat d12; + + GpuMat r1; + GpuMat r2; + + GpuMat sizes; + int maxSize; + + void create(int levels, int maxCapacity, bool isTempl); + }; + + typedef void (*set_func_t)(PtrStepb p1_pos, PtrStepb p1_theta, PtrStepb p2_pos, PtrStepb d12, PtrStepb r1, PtrStepb r2); + typedef void (*build_func_t)(const unsigned int* coordList, const float* thetaList, int pointsCount, + int* sizes, int maxSize, + float xi, float angleEpsilon, int levels, + float2 center, float maxDist); + + void buildFeatureList(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Feature& features, + set_func_t set_func, build_func_t build_func, bool isTempl, Point2d center = Point2d()); + + void calcOrientation(); + void calcScale(double angle); + void calcPosition(double angle, int angleVotes, double scale, int scaleVotes); + + Feature templFeatures_; + Feature imageFeatures_; + + std::vector< std::pair > angles_; + std::vector< std::pair > scales_; + + GpuMat hist_; + std::vector h_buf_; + }; + + double toRad(double a) + { + return a * CV_PI / 180.0; + } + + double clampAngle(double a) + { + double res = a; + + while (res > 360.0) + res -= 360.0; + while (res < 0) + res += 360.0; + + return res; + } + + bool angleEq(double a, double b, double eps = 1.0) + { + return (fabs(clampAngle(a - b)) <= eps); + } + + GeneralizedHoughGuilImpl::GeneralizedHoughGuilImpl() + { + maxBufferSize_ = 1000; + + xi_ = 90.0; + levels_ = 360; + angleEpsilon_ = 1.0; + + minAngle_ = 0.0; + maxAngle_ = 360.0; + angleStep_ = 1.0; + angleThresh_ = 15000; + + minScale_ = 0.5; + maxScale_ = 2.0; + scaleStep_ = 0.05; + scaleThresh_ = 1000; + + posThresh_ = 100; + } + + void GeneralizedHoughGuilImpl::processTempl() + { + using namespace cv::gpu::cudev::ght; + + buildFeatureList(templEdges_, templDx_, templDy_, templFeatures_, + Guil_Full_setTemplFeatures, Guil_Full_buildTemplFeatureList_gpu, + true, templCenter_); + + h_buf_.resize(templFeatures_.sizes.cols); + cudaSafeCall( cudaMemcpy(&h_buf_[0], templFeatures_.sizes.data, h_buf_.size() * sizeof(int), cudaMemcpyDeviceToHost) ); + templFeatures_.maxSize = *std::max_element(h_buf_.begin(), h_buf_.end()); + } + + void GeneralizedHoughGuilImpl::processImage() + { + using namespace cv::gpu::cudev::ght; + + CV_Assert( levels_ > 0 ); + CV_Assert( templFeatures_.sizes.cols == levels_ + 1 ); + CV_Assert( minAngle_ >= 0.0 && minAngle_ < maxAngle_ && maxAngle_ <= 360.0 ); + CV_Assert( angleStep_ > 0.0 && angleStep_ < 360.0 ); + CV_Assert( angleThresh_ > 0 ); + CV_Assert( minScale_ > 0.0 && minScale_ < maxScale_ ); + CV_Assert( scaleStep_ > 0.0 ); + CV_Assert( scaleThresh_ > 0 ); + CV_Assert( dp_ > 0.0 ); + CV_Assert( posThresh_ > 0 ); + + const double iAngleStep = 1.0 / angleStep_; + const int angleRange = cvCeil((maxAngle_ - minAngle_) * iAngleStep); + + const double iScaleStep = 1.0 / scaleStep_; + const int scaleRange = cvCeil((maxScale_ - minScale_) * iScaleStep); + + const double idp = 1.0 / dp_; + const int histRows = cvCeil(imageSize_.height * idp); + const int histCols = cvCeil(imageSize_.width * idp); + + ensureSizeIsEnough(histRows + 2, std::max(angleRange + 1, std::max(scaleRange + 1, histCols + 2)), CV_32SC1, hist_); + h_buf_.resize(std::max(angleRange + 1, scaleRange + 1)); + + ensureSizeIsEnough(2, maxBufferSize_, CV_32FC4, outBuf_); + + buildFeatureList(imageEdges_, imageDx_, imageDy_, imageFeatures_, + Guil_Full_setImageFeatures, Guil_Full_buildImageFeatureList_gpu, + false); + + calcOrientation(); + + for (size_t i = 0; i < angles_.size(); ++i) + { + const double angle = angles_[i].first; + const int angleVotes = angles_[i].second; + + calcScale(angle); + + for (size_t j = 0; j < scales_.size(); ++j) + { + const double scale = scales_[j].first; + const int scaleVotes = scales_[j].second; + + calcPosition(angle, angleVotes, scale, scaleVotes); + } + } + } + + void GeneralizedHoughGuilImpl::Feature::create(int levels, int maxCapacity, bool isTempl) + { + if (!isTempl) + { + ensureSizeIsEnough(levels + 1, maxCapacity, CV_32FC2, p1_pos); + ensureSizeIsEnough(levels + 1, maxCapacity, CV_32FC2, p2_pos); + } + + ensureSizeIsEnough(levels + 1, maxCapacity, CV_32FC1, p1_theta); + + ensureSizeIsEnough(levels + 1, maxCapacity, CV_32FC1, d12); + + if (isTempl) + { + ensureSizeIsEnough(levels + 1, maxCapacity, CV_32FC2, r1); + ensureSizeIsEnough(levels + 1, maxCapacity, CV_32FC2, r2); + } + + ensureSizeIsEnough(1, levels + 1, CV_32SC1, sizes); + sizes.setTo(Scalar::all(0)); + + maxSize = 0; + } + + void GeneralizedHoughGuilImpl::buildFeatureList(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Feature& features, + set_func_t set_func, build_func_t build_func, bool isTempl, Point2d center) + { + CV_Assert( levels_ > 0 ); + + const double maxDist = sqrt((double) templSize_.width * templSize_.width + templSize_.height * templSize_.height) * maxScale_; + + features.create(levels_, maxBufferSize_, isTempl); + set_func(features.p1_pos, features.p1_theta, features.p2_pos, features.d12, features.r1, features.r2); + + buildEdgePointList(edges, dx, dy); + + if (edgePointList_.cols > 0) + { + build_func(edgePointList_.ptr(0), edgePointList_.ptr(1), edgePointList_.cols, + features.sizes.ptr(), maxBufferSize_, (float)xi_, (float)angleEpsilon_, levels_, make_float2((float)center.x, (float)center.y), (float)maxDist); + } + } + + void GeneralizedHoughGuilImpl::calcOrientation() + { + using namespace cv::gpu::cudev::ght; + + const double iAngleStep = 1.0 / angleStep_; + const int angleRange = cvCeil((maxAngle_ - minAngle_) * iAngleStep); + + hist_.setTo(Scalar::all(0)); + Guil_Full_calcOHist_gpu(templFeatures_.sizes.ptr(), imageFeatures_.sizes.ptr(0), hist_.ptr(), + (float)minAngle_, (float)maxAngle_, (float)angleStep_, angleRange, levels_, templFeatures_.maxSize); + cudaSafeCall( cudaMemcpy(&h_buf_[0], hist_.data, h_buf_.size() * sizeof(int), cudaMemcpyDeviceToHost) ); + + angles_.clear(); + + for (int n = 0; n < angleRange; ++n) + { + if (h_buf_[n] >= angleThresh_) + { + const double angle = minAngle_ + n * angleStep_; + angles_.push_back(std::make_pair(angle, h_buf_[n])); + } + } + } + + void GeneralizedHoughGuilImpl::calcScale(double angle) + { + using namespace cv::gpu::cudev::ght; + + const double iScaleStep = 1.0 / scaleStep_; + const int scaleRange = cvCeil((maxScale_ - minScale_) * iScaleStep); + + hist_.setTo(Scalar::all(0)); + Guil_Full_calcSHist_gpu(templFeatures_.sizes.ptr(), imageFeatures_.sizes.ptr(0), hist_.ptr(), + (float)angle, (float)angleEpsilon_, (float)minScale_, (float)maxScale_, + (float)iScaleStep, scaleRange, levels_, templFeatures_.maxSize); + cudaSafeCall( cudaMemcpy(&h_buf_[0], hist_.data, h_buf_.size() * sizeof(int), cudaMemcpyDeviceToHost) ); + + scales_.clear(); + + for (int s = 0; s < scaleRange; ++s) + { + if (h_buf_[s] >= scaleThresh_) + { + const double scale = minScale_ + s * scaleStep_; + scales_.push_back(std::make_pair(scale, h_buf_[s])); + } + } + } + + void GeneralizedHoughGuilImpl::calcPosition(double angle, int angleVotes, double scale, int scaleVotes) + { + using namespace cv::gpu::cudev::ght; + + hist_.setTo(Scalar::all(0)); + Guil_Full_calcPHist_gpu(templFeatures_.sizes.ptr(), imageFeatures_.sizes.ptr(0), hist_, + (float)angle, (float)angleEpsilon_, (float)scale, (float)dp_, levels_, templFeatures_.maxSize); + + posCount_ = Guil_Full_findPosInHist_gpu(hist_, outBuf_.ptr(0), outBuf_.ptr(1), + posCount_, maxBufferSize_, (float)angle, angleVotes, + (float)scale, scaleVotes, (float)dp_, posThresh_); + } +} + +Ptr cv::gpu::createGeneralizedHoughGuil() +{ + return makePtr(); +} + +#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpuimgproc/src/gftt.cpp b/modules/gpuimgproc/src/gftt.cpp index cca1df444..0446b6cdb 100644 --- a/modules/gpuimgproc/src/gftt.cpp +++ b/modules/gpuimgproc/src/gftt.cpp @@ -45,9 +45,9 @@ using namespace cv; using namespace cv::gpu; -#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) +#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) || !defined(HAVE_OPENCV_GPUARITHM) -void cv::gpu::GoodFeaturesToTrackDetector_GPU::operator ()(const GpuMat&, GpuMat&, const GpuMat&) { throw_no_cuda(); } +Ptr cv::gpu::createGoodFeaturesToTrackDetector(int, int, double, double, int, bool, double) { throw_no_cuda(); return Ptr(); } #else /* !defined (HAVE_CUDA) */ @@ -60,117 +60,157 @@ namespace cv { namespace gpu { namespace cudev } }}} -void cv::gpu::GoodFeaturesToTrackDetector_GPU::operator ()(const GpuMat& image, GpuMat& corners, const GpuMat& mask) +namespace { -#ifndef HAVE_OPENCV_GPUARITHM - (void) image; - (void) corners; - (void) mask; - throw_no_cuda(); -#else - using namespace cv::gpu::cudev::gfft; - - CV_Assert(qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0); - CV_Assert(mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size())); - - ensureSizeIsEnough(image.size(), CV_32F, eig_); - - if (useHarrisDetector) - cornerHarris(image, eig_, Dx_, Dy_, buf_, blockSize, 3, harrisK); - else - cornerMinEigenVal(image, eig_, Dx_, Dy_, buf_, blockSize, 3); - - double maxVal = 0; - gpu::minMax(eig_, 0, &maxVal, GpuMat(), minMaxbuf_); - - ensureSizeIsEnough(1, std::max(1000, static_cast(image.size().area() * 0.05)), CV_32FC2, tmpCorners_); - - int total = findCorners_gpu(eig_, static_cast(maxVal * qualityLevel), mask, tmpCorners_.ptr(), tmpCorners_.cols); - - if (total == 0) + class GoodFeaturesToTrackDetector : public CornersDetector { - corners.release(); - return; + public: + GoodFeaturesToTrackDetector(int srcType, int maxCorners, double qualityLevel, double minDistance, + int blockSize, bool useHarrisDetector, double harrisK); + + void detect(InputArray image, OutputArray corners, InputArray mask = noArray()); + + private: + int maxCorners_; + double qualityLevel_; + double minDistance_; + + Ptr cornerCriteria_; + + GpuMat Dx_; + GpuMat Dy_; + GpuMat buf_; + GpuMat eig_; + GpuMat minMaxbuf_; + GpuMat tmpCorners_; + }; + + GoodFeaturesToTrackDetector::GoodFeaturesToTrackDetector(int srcType, int maxCorners, double qualityLevel, double minDistance, + int blockSize, bool useHarrisDetector, double harrisK) : + maxCorners_(maxCorners), qualityLevel_(qualityLevel), minDistance_(minDistance) + { + CV_Assert( qualityLevel_ > 0 && minDistance_ >= 0 && maxCorners_ >= 0 ); + + cornerCriteria_ = useHarrisDetector ? + gpu::createHarrisCorner(srcType, blockSize, 3, harrisK) : + gpu::createMinEigenValCorner(srcType, blockSize, 3); } - sortCorners_gpu(eig_, tmpCorners_.ptr(), total); - - if (minDistance < 1) - tmpCorners_.colRange(0, maxCorners > 0 ? std::min(maxCorners, total) : total).copyTo(corners); - else + void GoodFeaturesToTrackDetector::detect(InputArray _image, OutputArray _corners, InputArray _mask) { - std::vector tmp(total); - Mat tmpMat(1, total, CV_32FC2, (void*)&tmp[0]); - tmpCorners_.colRange(0, total).download(tmpMat); + using namespace cv::gpu::cudev::gfft; - std::vector tmp2; - tmp2.reserve(total); + GpuMat image = _image.getGpuMat(); + GpuMat mask = _mask.getGpuMat(); - const int cell_size = cvRound(minDistance); - const int grid_width = (image.cols + cell_size - 1) / cell_size; - const int grid_height = (image.rows + cell_size - 1) / cell_size; + CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) ); - std::vector< std::vector > grid(grid_width * grid_height); + ensureSizeIsEnough(image.size(), CV_32FC1, eig_); + cornerCriteria_->compute(image, eig_); - for (int i = 0; i < total; ++i) + double maxVal = 0; + gpu::minMax(eig_, 0, &maxVal, noArray(), minMaxbuf_); + + ensureSizeIsEnough(1, std::max(1000, static_cast(image.size().area() * 0.05)), CV_32FC2, tmpCorners_); + + int total = findCorners_gpu(eig_, static_cast(maxVal * qualityLevel_), mask, tmpCorners_.ptr(), tmpCorners_.cols); + + if (total == 0) { - Point2f p = tmp[i]; + _corners.release(); + return; + } - bool good = true; + sortCorners_gpu(eig_, tmpCorners_.ptr(), total); - int x_cell = static_cast(p.x / cell_size); - int y_cell = static_cast(p.y / cell_size); + if (minDistance_ < 1) + { + tmpCorners_.colRange(0, maxCorners_ > 0 ? std::min(maxCorners_, total) : total).copyTo(_corners); + } + else + { + std::vector tmp(total); + Mat tmpMat(1, total, CV_32FC2, (void*)&tmp[0]); + tmpCorners_.colRange(0, total).download(tmpMat); - int x1 = x_cell - 1; - int y1 = y_cell - 1; - int x2 = x_cell + 1; - int y2 = y_cell + 1; + std::vector tmp2; + tmp2.reserve(total); - // boundary check - x1 = std::max(0, x1); - y1 = std::max(0, y1); - x2 = std::min(grid_width - 1, x2); - y2 = std::min(grid_height - 1, y2); + const int cell_size = cvRound(minDistance_); + const int grid_width = (image.cols + cell_size - 1) / cell_size; + const int grid_height = (image.rows + cell_size - 1) / cell_size; - for (int yy = y1; yy <= y2; yy++) + std::vector< std::vector > grid(grid_width * grid_height); + + for (int i = 0; i < total; ++i) { - for (int xx = x1; xx <= x2; xx++) + Point2f p = tmp[i]; + + bool good = true; + + int x_cell = static_cast(p.x / cell_size); + int y_cell = static_cast(p.y / cell_size); + + int x1 = x_cell - 1; + int y1 = y_cell - 1; + int x2 = x_cell + 1; + int y2 = y_cell + 1; + + // boundary check + x1 = std::max(0, x1); + y1 = std::max(0, y1); + x2 = std::min(grid_width - 1, x2); + y2 = std::min(grid_height - 1, y2); + + for (int yy = y1; yy <= y2; yy++) { - std::vector& m = grid[yy * grid_width + xx]; - - if (!m.empty()) + for (int xx = x1; xx <= x2; xx++) { - for(size_t j = 0; j < m.size(); j++) - { - float dx = p.x - m[j].x; - float dy = p.y - m[j].y; + std::vector& m = grid[yy * grid_width + xx]; - if (dx * dx + dy * dy < minDistance * minDistance) + if (!m.empty()) + { + for(size_t j = 0; j < m.size(); j++) { - good = false; - goto break_out; + float dx = p.x - m[j].x; + float dy = p.y - m[j].y; + + if (dx * dx + dy * dy < minDistance_ * minDistance_) + { + good = false; + goto break_out; + } } } } } + + break_out: + + if(good) + { + grid[y_cell * grid_width + x_cell].push_back(p); + + tmp2.push_back(p); + + if (maxCorners_ > 0 && tmp2.size() == static_cast(maxCorners_)) + break; + } } - break_out: + _corners.create(1, static_cast(tmp2.size()), CV_32FC2); + GpuMat corners = _corners.getGpuMat(); - if(good) - { - grid[y_cell * grid_width + x_cell].push_back(p); - - tmp2.push_back(p); - - if (maxCorners > 0 && tmp2.size() == static_cast(maxCorners)) - break; - } + corners.upload(Mat(1, static_cast(tmp2.size()), CV_32FC2, &tmp2[0])); } - - corners.upload(Mat(1, static_cast(tmp2.size()), CV_32FC2, &tmp2[0])); } -#endif +} + +Ptr cv::gpu::createGoodFeaturesToTrackDetector(int srcType, int maxCorners, double qualityLevel, double minDistance, + int blockSize, bool useHarrisDetector, double harrisK) +{ + return Ptr( + new GoodFeaturesToTrackDetector(srcType, maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector, harrisK)); } #endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpuimgproc/src/histogram.cpp b/modules/gpuimgproc/src/histogram.cpp index 3227dac6c..eb78ee0de 100644 --- a/modules/gpuimgproc/src/histogram.cpp +++ b/modules/gpuimgproc/src/histogram.cpp @@ -47,319 +47,22 @@ using namespace cv::gpu; #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) -void cv::gpu::evenLevels(GpuMat&, int, int, int) { throw_no_cuda(); } +void cv::gpu::calcHist(InputArray, OutputArray, Stream&) { throw_no_cuda(); } -void cv::gpu::histEven(const GpuMat&, GpuMat&, int, int, int, Stream&) { throw_no_cuda(); } -void cv::gpu::histEven(const GpuMat&, GpuMat&, GpuMat&, int, int, int, Stream&) { throw_no_cuda(); } -void cv::gpu::histEven(const GpuMat&, GpuMat*, int*, int*, int*, Stream&) { throw_no_cuda(); } -void cv::gpu::histEven(const GpuMat&, GpuMat*, GpuMat&, int*, int*, int*, Stream&) { throw_no_cuda(); } - -void cv::gpu::histRange(const GpuMat&, GpuMat&, const GpuMat&, Stream&) { throw_no_cuda(); } -void cv::gpu::histRange(const GpuMat&, GpuMat&, const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); } -void cv::gpu::histRange(const GpuMat&, GpuMat*, const GpuMat*, Stream&) { throw_no_cuda(); } -void cv::gpu::histRange(const GpuMat&, GpuMat*, const GpuMat*, GpuMat&, Stream&) { throw_no_cuda(); } - -void cv::gpu::calcHist(const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); } - -void cv::gpu::equalizeHist(const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); } -void cv::gpu::equalizeHist(const GpuMat&, GpuMat&, GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); } +void cv::gpu::equalizeHist(InputArray, OutputArray, InputOutputArray, Stream&) { throw_no_cuda(); } cv::Ptr cv::gpu::createCLAHE(double, cv::Size) { throw_no_cuda(); return cv::Ptr(); } +void cv::gpu::evenLevels(OutputArray, int, int, int) { throw_no_cuda(); } + +void cv::gpu::histEven(InputArray, OutputArray, InputOutputArray, int, int, int, Stream&) { throw_no_cuda(); } +void cv::gpu::histEven(InputArray, GpuMat*, InputOutputArray, int*, int*, int*, Stream&) { throw_no_cuda(); } + +void cv::gpu::histRange(InputArray, OutputArray, InputArray, InputOutputArray, Stream&) { throw_no_cuda(); } +void cv::gpu::histRange(InputArray, GpuMat*, const GpuMat*, InputOutputArray, Stream&) { throw_no_cuda(); } + #else /* !defined (HAVE_CUDA) */ -//////////////////////////////////////////////////////////////////////// -// NPP Histogram - -namespace -{ - typedef NppStatus (*get_buf_size_c1_t)(NppiSize oSizeROI, int nLevels, int* hpBufferSize); - typedef NppStatus (*get_buf_size_c4_t)(NppiSize oSizeROI, int nLevels[], int* hpBufferSize); - - template struct NppHistogramEvenFuncC1 - { - typedef typename NPPTypeTraits::npp_type src_t; - - typedef NppStatus (*func_ptr)(const src_t* pSrc, int nSrcStep, NppiSize oSizeROI, Npp32s * pHist, - int nLevels, Npp32s nLowerLevel, Npp32s nUpperLevel, Npp8u * pBuffer); - }; - template struct NppHistogramEvenFuncC4 - { - typedef typename NPPTypeTraits::npp_type src_t; - - typedef NppStatus (*func_ptr)(const src_t* pSrc, int nSrcStep, NppiSize oSizeROI, - Npp32s * pHist[4], int nLevels[4], Npp32s nLowerLevel[4], Npp32s nUpperLevel[4], Npp8u * pBuffer); - }; - - template::func_ptr func, get_buf_size_c1_t get_buf_size> - struct NppHistogramEvenC1 - { - typedef typename NppHistogramEvenFuncC1::src_t src_t; - - static void hist(const GpuMat& src, GpuMat& hist, GpuMat& buffer, int histSize, int lowerLevel, int upperLevel, cudaStream_t stream) - { - int levels = histSize + 1; - hist.create(1, histSize, CV_32S); - - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - int buf_size; - get_buf_size(sz, levels, &buf_size); - - ensureSizeIsEnough(1, buf_size, CV_8U, buffer); - - NppStreamHandler h(stream); - - nppSafeCall( func(src.ptr(), static_cast(src.step), sz, hist.ptr(), levels, - lowerLevel, upperLevel, buffer.ptr()) ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; - template::func_ptr func, get_buf_size_c4_t get_buf_size> - struct NppHistogramEvenC4 - { - typedef typename NppHistogramEvenFuncC4::src_t src_t; - - static void hist(const GpuMat& src, GpuMat hist[4], GpuMat& buffer, int histSize[4], int lowerLevel[4], int upperLevel[4], cudaStream_t stream) - { - int levels[] = {histSize[0] + 1, histSize[1] + 1, histSize[2] + 1, histSize[3] + 1}; - hist[0].create(1, histSize[0], CV_32S); - hist[1].create(1, histSize[1], CV_32S); - hist[2].create(1, histSize[2], CV_32S); - hist[3].create(1, histSize[3], CV_32S); - - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - Npp32s* pHist[] = {hist[0].ptr(), hist[1].ptr(), hist[2].ptr(), hist[3].ptr()}; - - int buf_size; - get_buf_size(sz, levels, &buf_size); - - ensureSizeIsEnough(1, buf_size, CV_8U, buffer); - - NppStreamHandler h(stream); - - nppSafeCall( func(src.ptr(), static_cast(src.step), sz, pHist, levels, lowerLevel, upperLevel, buffer.ptr()) ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; - - template struct NppHistogramRangeFuncC1 - { - typedef typename NPPTypeTraits::npp_type src_t; - typedef Npp32s level_t; - enum {LEVEL_TYPE_CODE=CV_32SC1}; - - typedef NppStatus (*func_ptr)(const src_t* pSrc, int nSrcStep, NppiSize oSizeROI, Npp32s* pHist, - const Npp32s* pLevels, int nLevels, Npp8u* pBuffer); - }; - template<> struct NppHistogramRangeFuncC1 - { - typedef Npp32f src_t; - typedef Npp32f level_t; - enum {LEVEL_TYPE_CODE=CV_32FC1}; - - typedef NppStatus (*func_ptr)(const Npp32f* pSrc, int nSrcStep, NppiSize oSizeROI, Npp32s* pHist, - const Npp32f* pLevels, int nLevels, Npp8u* pBuffer); - }; - template struct NppHistogramRangeFuncC4 - { - typedef typename NPPTypeTraits::npp_type src_t; - typedef Npp32s level_t; - enum {LEVEL_TYPE_CODE=CV_32SC1}; - - typedef NppStatus (*func_ptr)(const src_t* pSrc, int nSrcStep, NppiSize oSizeROI, Npp32s* pHist[4], - const Npp32s* pLevels[4], int nLevels[4], Npp8u* pBuffer); - }; - template<> struct NppHistogramRangeFuncC4 - { - typedef Npp32f src_t; - typedef Npp32f level_t; - enum {LEVEL_TYPE_CODE=CV_32FC1}; - - typedef NppStatus (*func_ptr)(const Npp32f* pSrc, int nSrcStep, NppiSize oSizeROI, Npp32s* pHist[4], - const Npp32f* pLevels[4], int nLevels[4], Npp8u* pBuffer); - }; - - template::func_ptr func, get_buf_size_c1_t get_buf_size> - struct NppHistogramRangeC1 - { - typedef typename NppHistogramRangeFuncC1::src_t src_t; - typedef typename NppHistogramRangeFuncC1::level_t level_t; - enum {LEVEL_TYPE_CODE=NppHistogramRangeFuncC1::LEVEL_TYPE_CODE}; - - static void hist(const GpuMat& src, GpuMat& hist, const GpuMat& levels, GpuMat& buffer, cudaStream_t stream) - { - CV_Assert(levels.type() == LEVEL_TYPE_CODE && levels.rows == 1); - - hist.create(1, levels.cols - 1, CV_32S); - - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - int buf_size; - get_buf_size(sz, levels.cols, &buf_size); - - ensureSizeIsEnough(1, buf_size, CV_8U, buffer); - - NppStreamHandler h(stream); - - nppSafeCall( func(src.ptr(), static_cast(src.step), sz, hist.ptr(), levels.ptr(), levels.cols, buffer.ptr()) ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; - template::func_ptr func, get_buf_size_c4_t get_buf_size> - struct NppHistogramRangeC4 - { - typedef typename NppHistogramRangeFuncC4::src_t src_t; - typedef typename NppHistogramRangeFuncC1::level_t level_t; - enum {LEVEL_TYPE_CODE=NppHistogramRangeFuncC1::LEVEL_TYPE_CODE}; - - static void hist(const GpuMat& src, GpuMat hist[4], const GpuMat levels[4], GpuMat& buffer, cudaStream_t stream) - { - CV_Assert(levels[0].type() == LEVEL_TYPE_CODE && levels[0].rows == 1); - CV_Assert(levels[1].type() == LEVEL_TYPE_CODE && levels[1].rows == 1); - CV_Assert(levels[2].type() == LEVEL_TYPE_CODE && levels[2].rows == 1); - CV_Assert(levels[3].type() == LEVEL_TYPE_CODE && levels[3].rows == 1); - - hist[0].create(1, levels[0].cols - 1, CV_32S); - hist[1].create(1, levels[1].cols - 1, CV_32S); - hist[2].create(1, levels[2].cols - 1, CV_32S); - hist[3].create(1, levels[3].cols - 1, CV_32S); - - Npp32s* pHist[] = {hist[0].ptr(), hist[1].ptr(), hist[2].ptr(), hist[3].ptr()}; - int nLevels[] = {levels[0].cols, levels[1].cols, levels[2].cols, levels[3].cols}; - const level_t* pLevels[] = {levels[0].ptr(), levels[1].ptr(), levels[2].ptr(), levels[3].ptr()}; - - NppiSize sz; - sz.width = src.cols; - sz.height = src.rows; - - int buf_size; - get_buf_size(sz, nLevels, &buf_size); - - ensureSizeIsEnough(1, buf_size, CV_8U, buffer); - - NppStreamHandler h(stream); - - nppSafeCall( func(src.ptr(), static_cast(src.step), sz, pHist, pLevels, nLevels, buffer.ptr()) ); - - if (stream == 0) - cudaSafeCall( cudaDeviceSynchronize() ); - } - }; -} - -void cv::gpu::evenLevels(GpuMat& levels, int nLevels, int lowerLevel, int upperLevel) -{ - Mat host_levels(1, nLevels, CV_32SC1); - nppSafeCall( nppiEvenLevelsHost_32s(host_levels.ptr(), nLevels, lowerLevel, upperLevel) ); - levels.upload(host_levels); -} - -void cv::gpu::histEven(const GpuMat& src, GpuMat& hist, int histSize, int lowerLevel, int upperLevel, Stream& stream) -{ - GpuMat buf; - histEven(src, hist, buf, histSize, lowerLevel, upperLevel, stream); -} - -void cv::gpu::histEven(const GpuMat& src, GpuMat& hist, GpuMat& buf, int histSize, int lowerLevel, int upperLevel, Stream& stream) -{ - CV_Assert(src.type() == CV_8UC1 || src.type() == CV_16UC1 || src.type() == CV_16SC1 ); - - typedef void (*hist_t)(const GpuMat& src, GpuMat& hist, GpuMat& buf, int levels, int lowerLevel, int upperLevel, cudaStream_t stream); - static const hist_t hist_callers[] = - { - NppHistogramEvenC1::hist, - 0, - NppHistogramEvenC1::hist, - NppHistogramEvenC1::hist - }; - - hist_callers[src.depth()](src, hist, buf, histSize, lowerLevel, upperLevel, StreamAccessor::getStream(stream)); -} - -void cv::gpu::histEven(const GpuMat& src, GpuMat hist[4], int histSize[4], int lowerLevel[4], int upperLevel[4], Stream& stream) -{ - GpuMat buf; - histEven(src, hist, buf, histSize, lowerLevel, upperLevel, stream); -} - -void cv::gpu::histEven(const GpuMat& src, GpuMat hist[4], GpuMat& buf, int histSize[4], int lowerLevel[4], int upperLevel[4], Stream& stream) -{ - CV_Assert(src.type() == CV_8UC4 || src.type() == CV_16UC4 || src.type() == CV_16SC4 ); - - typedef void (*hist_t)(const GpuMat& src, GpuMat hist[4], GpuMat& buf, int levels[4], int lowerLevel[4], int upperLevel[4], cudaStream_t stream); - static const hist_t hist_callers[] = - { - NppHistogramEvenC4::hist, - 0, - NppHistogramEvenC4::hist, - NppHistogramEvenC4::hist - }; - - hist_callers[src.depth()](src, hist, buf, histSize, lowerLevel, upperLevel, StreamAccessor::getStream(stream)); -} - -void cv::gpu::histRange(const GpuMat& src, GpuMat& hist, const GpuMat& levels, Stream& stream) -{ - GpuMat buf; - histRange(src, hist, levels, buf, stream); -} - -void cv::gpu::histRange(const GpuMat& src, GpuMat& hist, const GpuMat& levels, GpuMat& buf, Stream& stream) -{ - CV_Assert(src.type() == CV_8UC1 || src.type() == CV_16UC1 || src.type() == CV_16SC1 || src.type() == CV_32FC1); - - typedef void (*hist_t)(const GpuMat& src, GpuMat& hist, const GpuMat& levels, GpuMat& buf, cudaStream_t stream); - static const hist_t hist_callers[] = - { - NppHistogramRangeC1::hist, - 0, - NppHistogramRangeC1::hist, - NppHistogramRangeC1::hist, - 0, - NppHistogramRangeC1::hist - }; - - hist_callers[src.depth()](src, hist, levels, buf, StreamAccessor::getStream(stream)); -} - -void cv::gpu::histRange(const GpuMat& src, GpuMat hist[4], const GpuMat levels[4], Stream& stream) -{ - GpuMat buf; - histRange(src, hist, levels, buf, stream); -} - -void cv::gpu::histRange(const GpuMat& src, GpuMat hist[4], const GpuMat levels[4], GpuMat& buf, Stream& stream) -{ - CV_Assert(src.type() == CV_8UC4 || src.type() == CV_16UC4 || src.type() == CV_16SC4 || src.type() == CV_32FC4); - - typedef void (*hist_t)(const GpuMat& src, GpuMat hist[4], const GpuMat levels[4], GpuMat& buf, cudaStream_t stream); - static const hist_t hist_callers[] = - { - NppHistogramRangeC4::hist, - 0, - NppHistogramRangeC4::hist, - NppHistogramRangeC4::hist, - 0, - NppHistogramRangeC4::hist - }; - - hist_callers[src.depth()](src, hist, levels, buf, StreamAccessor::getStream(stream)); -} - //////////////////////////////////////////////////////////////////////// // calcHist @@ -368,12 +71,16 @@ namespace hist void histogram256(PtrStepSzb src, int* hist, cudaStream_t stream); } -void cv::gpu::calcHist(const GpuMat& src, GpuMat& hist, Stream& stream) +void cv::gpu::calcHist(InputArray _src, OutputArray _hist, Stream& stream) { - CV_Assert(src.type() == CV_8UC1); + GpuMat src = _src.getGpuMat(); - hist.create(1, 256, CV_32SC1); - hist.setTo(Scalar::all(0)); + CV_Assert( src.type() == CV_8UC1 ); + + _hist.create(1, 256, CV_32SC1); + GpuMat hist = _hist.getGpuMat(); + + hist.setTo(Scalar::all(0), stream); hist::histogram256(src, hist.ptr(), StreamAccessor::getStream(stream)); } @@ -386,31 +93,30 @@ namespace hist void equalizeHist(PtrStepSzb src, PtrStepSzb dst, const int* lut, cudaStream_t stream); } -void cv::gpu::equalizeHist(const GpuMat& src, GpuMat& dst, Stream& stream) +void cv::gpu::equalizeHist(InputArray _src, OutputArray _dst, InputOutputArray _buf, Stream& _stream) { - GpuMat hist; - GpuMat buf; - equalizeHist(src, dst, hist, buf, stream); -} + GpuMat src = _src.getGpuMat(); -void cv::gpu::equalizeHist(const GpuMat& src, GpuMat& dst, GpuMat& hist, GpuMat& buf, Stream& s) -{ - CV_Assert(src.type() == CV_8UC1); + CV_Assert( src.type() == CV_8UC1 ); - dst.create(src.size(), src.type()); + _dst.create(src.size(), src.type()); + GpuMat dst = _dst.getGpuMat(); int intBufSize; nppSafeCall( nppsIntegralGetBufferSize_32s(256, &intBufSize) ); - ensureSizeIsEnough(1, intBufSize + 256 * sizeof(int), CV_8UC1, buf); + size_t bufSize = intBufSize + 2 * 256 * sizeof(int); - GpuMat intBuf(1, intBufSize, CV_8UC1, buf.ptr()); - GpuMat lut(1, 256, CV_32S, buf.ptr() + intBufSize); + ensureSizeIsEnough(1, static_cast(bufSize), CV_8UC1, _buf); + GpuMat buf = _buf.getGpuMat(); - calcHist(src, hist, s); + GpuMat hist(1, 256, CV_32SC1, buf.data); + GpuMat lut(1, 256, CV_32SC1, buf.data + 256 * sizeof(int)); + GpuMat intBuf(1, intBufSize, CV_8UC1, buf.data + 2 * 256 * sizeof(int)); - cudaStream_t stream = StreamAccessor::getStream(s); + gpu::calcHist(src, hist, _stream); + cudaStream_t stream = StreamAccessor::getStream(_stream); NppStreamHandler h(stream); nppSafeCall( nppsIntegral_32s(hist.ptr(), lut.ptr(), 256, intBuf.ptr()) ); @@ -551,7 +257,323 @@ namespace cv::Ptr cv::gpu::createCLAHE(double clipLimit, cv::Size tileGridSize) { - return new CLAHE_Impl(clipLimit, tileGridSize.width, tileGridSize.height); + return makePtr(clipLimit, tileGridSize.width, tileGridSize.height); +} + +//////////////////////////////////////////////////////////////////////// +// NPP Histogram + +namespace +{ + typedef NppStatus (*get_buf_size_c1_t)(NppiSize oSizeROI, int nLevels, int* hpBufferSize); + typedef NppStatus (*get_buf_size_c4_t)(NppiSize oSizeROI, int nLevels[], int* hpBufferSize); + + template struct NppHistogramEvenFuncC1 + { + typedef typename NPPTypeTraits::npp_type src_t; + + typedef NppStatus (*func_ptr)(const src_t* pSrc, int nSrcStep, NppiSize oSizeROI, Npp32s * pHist, + int nLevels, Npp32s nLowerLevel, Npp32s nUpperLevel, Npp8u * pBuffer); + }; + template struct NppHistogramEvenFuncC4 + { + typedef typename NPPTypeTraits::npp_type src_t; + + typedef NppStatus (*func_ptr)(const src_t* pSrc, int nSrcStep, NppiSize oSizeROI, + Npp32s * pHist[4], int nLevels[4], Npp32s nLowerLevel[4], Npp32s nUpperLevel[4], Npp8u * pBuffer); + }; + + template::func_ptr func, get_buf_size_c1_t get_buf_size> + struct NppHistogramEvenC1 + { + typedef typename NppHistogramEvenFuncC1::src_t src_t; + + static void hist(const GpuMat& src, OutputArray _hist, InputOutputArray _buf, int histSize, int lowerLevel, int upperLevel, cudaStream_t stream) + { + const int levels = histSize + 1; + + _hist.create(1, histSize, CV_32S); + GpuMat hist = _hist.getGpuMat(); + + NppiSize sz; + sz.width = src.cols; + sz.height = src.rows; + + int buf_size; + get_buf_size(sz, levels, &buf_size); + + ensureSizeIsEnough(1, buf_size, CV_8UC1, _buf); + GpuMat buf = _buf.getGpuMat(); + + NppStreamHandler h(stream); + + nppSafeCall( func(src.ptr(), static_cast(src.step), sz, hist.ptr(), levels, + lowerLevel, upperLevel, buf.ptr()) ); + + if (stream == 0) + cudaSafeCall( cudaDeviceSynchronize() ); + } + }; + template::func_ptr func, get_buf_size_c4_t get_buf_size> + struct NppHistogramEvenC4 + { + typedef typename NppHistogramEvenFuncC4::src_t src_t; + + static void hist(const GpuMat& src, GpuMat hist[4],InputOutputArray _buf, int histSize[4], int lowerLevel[4], int upperLevel[4], cudaStream_t stream) + { + int levels[] = {histSize[0] + 1, histSize[1] + 1, histSize[2] + 1, histSize[3] + 1}; + hist[0].create(1, histSize[0], CV_32S); + hist[1].create(1, histSize[1], CV_32S); + hist[2].create(1, histSize[2], CV_32S); + hist[3].create(1, histSize[3], CV_32S); + + NppiSize sz; + sz.width = src.cols; + sz.height = src.rows; + + Npp32s* pHist[] = {hist[0].ptr(), hist[1].ptr(), hist[2].ptr(), hist[3].ptr()}; + + int buf_size; + get_buf_size(sz, levels, &buf_size); + + ensureSizeIsEnough(1, buf_size, CV_8U, _buf); + GpuMat buf = _buf.getGpuMat(); + + NppStreamHandler h(stream); + + nppSafeCall( func(src.ptr(), static_cast(src.step), sz, pHist, levels, lowerLevel, upperLevel, buf.ptr()) ); + + if (stream == 0) + cudaSafeCall( cudaDeviceSynchronize() ); + } + }; + + template struct NppHistogramRangeFuncC1 + { + typedef typename NPPTypeTraits::npp_type src_t; + typedef Npp32s level_t; + enum {LEVEL_TYPE_CODE=CV_32SC1}; + + typedef NppStatus (*func_ptr)(const src_t* pSrc, int nSrcStep, NppiSize oSizeROI, Npp32s* pHist, + const Npp32s* pLevels, int nLevels, Npp8u* pBuffer); + }; + template<> struct NppHistogramRangeFuncC1 + { + typedef Npp32f src_t; + typedef Npp32f level_t; + enum {LEVEL_TYPE_CODE=CV_32FC1}; + + typedef NppStatus (*func_ptr)(const Npp32f* pSrc, int nSrcStep, NppiSize oSizeROI, Npp32s* pHist, + const Npp32f* pLevels, int nLevels, Npp8u* pBuffer); + }; + template struct NppHistogramRangeFuncC4 + { + typedef typename NPPTypeTraits::npp_type src_t; + typedef Npp32s level_t; + enum {LEVEL_TYPE_CODE=CV_32SC1}; + + typedef NppStatus (*func_ptr)(const src_t* pSrc, int nSrcStep, NppiSize oSizeROI, Npp32s* pHist[4], + const Npp32s* pLevels[4], int nLevels[4], Npp8u* pBuffer); + }; + template<> struct NppHistogramRangeFuncC4 + { + typedef Npp32f src_t; + typedef Npp32f level_t; + enum {LEVEL_TYPE_CODE=CV_32FC1}; + + typedef NppStatus (*func_ptr)(const Npp32f* pSrc, int nSrcStep, NppiSize oSizeROI, Npp32s* pHist[4], + const Npp32f* pLevels[4], int nLevels[4], Npp8u* pBuffer); + }; + + template::func_ptr func, get_buf_size_c1_t get_buf_size> + struct NppHistogramRangeC1 + { + typedef typename NppHistogramRangeFuncC1::src_t src_t; + typedef typename NppHistogramRangeFuncC1::level_t level_t; + enum {LEVEL_TYPE_CODE=NppHistogramRangeFuncC1::LEVEL_TYPE_CODE}; + + static void hist(const GpuMat& src, OutputArray _hist, const GpuMat& levels, InputOutputArray _buf, cudaStream_t stream) + { + CV_Assert( levels.type() == LEVEL_TYPE_CODE && levels.rows == 1 ); + + _hist.create(1, levels.cols - 1, CV_32S); + GpuMat hist = _hist.getGpuMat(); + + NppiSize sz; + sz.width = src.cols; + sz.height = src.rows; + + int buf_size; + get_buf_size(sz, levels.cols, &buf_size); + + ensureSizeIsEnough(1, buf_size, CV_8U, _buf); + GpuMat buf = _buf.getGpuMat(); + + NppStreamHandler h(stream); + + nppSafeCall( func(src.ptr(), static_cast(src.step), sz, hist.ptr(), levels.ptr(), levels.cols, buf.ptr()) ); + + if (stream == 0) + cudaSafeCall( cudaDeviceSynchronize() ); + } + }; + template::func_ptr func, get_buf_size_c4_t get_buf_size> + struct NppHistogramRangeC4 + { + typedef typename NppHistogramRangeFuncC4::src_t src_t; + typedef typename NppHistogramRangeFuncC1::level_t level_t; + enum {LEVEL_TYPE_CODE=NppHistogramRangeFuncC1::LEVEL_TYPE_CODE}; + + static void hist(const GpuMat& src, GpuMat hist[4], const GpuMat levels[4],InputOutputArray _buf, cudaStream_t stream) + { + CV_Assert( levels[0].type() == LEVEL_TYPE_CODE && levels[0].rows == 1 ); + CV_Assert( levels[1].type() == LEVEL_TYPE_CODE && levels[1].rows == 1 ); + CV_Assert( levels[2].type() == LEVEL_TYPE_CODE && levels[2].rows == 1 ); + CV_Assert( levels[3].type() == LEVEL_TYPE_CODE && levels[3].rows == 1 ); + + hist[0].create(1, levels[0].cols - 1, CV_32S); + hist[1].create(1, levels[1].cols - 1, CV_32S); + hist[2].create(1, levels[2].cols - 1, CV_32S); + hist[3].create(1, levels[3].cols - 1, CV_32S); + + Npp32s* pHist[] = {hist[0].ptr(), hist[1].ptr(), hist[2].ptr(), hist[3].ptr()}; + int nLevels[] = {levels[0].cols, levels[1].cols, levels[2].cols, levels[3].cols}; + const level_t* pLevels[] = {levels[0].ptr(), levels[1].ptr(), levels[2].ptr(), levels[3].ptr()}; + + NppiSize sz; + sz.width = src.cols; + sz.height = src.rows; + + int buf_size; + get_buf_size(sz, nLevels, &buf_size); + + ensureSizeIsEnough(1, buf_size, CV_8U, _buf); + GpuMat buf = _buf.getGpuMat(); + + NppStreamHandler h(stream); + + nppSafeCall( func(src.ptr(), static_cast(src.step), sz, pHist, pLevels, nLevels, buf.ptr()) ); + + if (stream == 0) + cudaSafeCall( cudaDeviceSynchronize() ); + } + }; +} + +void cv::gpu::evenLevels(OutputArray _levels, int nLevels, int lowerLevel, int upperLevel) +{ + const int kind = _levels.kind(); + + _levels.create(1, nLevels, CV_32SC1); + + Mat host_levels; + if (kind == _InputArray::GPU_MAT) + host_levels.create(1, nLevels, CV_32SC1); + else + host_levels = _levels.getMat(); + + nppSafeCall( nppiEvenLevelsHost_32s(host_levels.ptr(), nLevels, lowerLevel, upperLevel) ); + + if (kind == _InputArray::GPU_MAT) + _levels.getGpuMatRef().upload(host_levels); +} + +namespace hist +{ + void histEven8u(PtrStepSzb src, int* hist, int binCount, int lowerLevel, int upperLevel, cudaStream_t stream); +} + +namespace +{ + void histEven8u(const GpuMat& src, GpuMat& hist, int histSize, int lowerLevel, int upperLevel, cudaStream_t stream) + { + hist.create(1, histSize, CV_32S); + cudaSafeCall( cudaMemsetAsync(hist.data, 0, histSize * sizeof(int), stream) ); + hist::histEven8u(src, hist.ptr(), histSize, lowerLevel, upperLevel, stream); + } +} + +void cv::gpu::histEven(InputArray _src, OutputArray hist, InputOutputArray buf, int histSize, int lowerLevel, int upperLevel, Stream& stream) +{ + typedef void (*hist_t)(const GpuMat& src, OutputArray hist, InputOutputArray buf, int levels, int lowerLevel, int upperLevel, cudaStream_t stream); + static const hist_t hist_callers[] = + { + NppHistogramEvenC1::hist, + 0, + NppHistogramEvenC1::hist, + NppHistogramEvenC1::hist + }; + + GpuMat src = _src.getGpuMat(); + + if (src.depth() == CV_8U && deviceSupports(FEATURE_SET_COMPUTE_30)) + { + histEven8u(src, hist.getGpuMatRef(), histSize, lowerLevel, upperLevel, StreamAccessor::getStream(stream)); + return; + } + + CV_Assert( src.type() == CV_8UC1 || src.type() == CV_16UC1 || src.type() == CV_16SC1 ); + + hist_callers[src.depth()](src, hist, buf, histSize, lowerLevel, upperLevel, StreamAccessor::getStream(stream)); +} + +void cv::gpu::histEven(InputArray _src, GpuMat hist[4], InputOutputArray buf, int histSize[4], int lowerLevel[4], int upperLevel[4], Stream& stream) +{ + typedef void (*hist_t)(const GpuMat& src, GpuMat hist[4], InputOutputArray buf, int levels[4], int lowerLevel[4], int upperLevel[4], cudaStream_t stream); + static const hist_t hist_callers[] = + { + NppHistogramEvenC4::hist, + 0, + NppHistogramEvenC4::hist, + NppHistogramEvenC4::hist + }; + + GpuMat src = _src.getGpuMat(); + + CV_Assert( src.type() == CV_8UC4 || src.type() == CV_16UC4 || src.type() == CV_16SC4 ); + + hist_callers[src.depth()](src, hist, buf, histSize, lowerLevel, upperLevel, StreamAccessor::getStream(stream)); +} + +void cv::gpu::histRange(InputArray _src, OutputArray hist, InputArray _levels, InputOutputArray buf, Stream& stream) +{ + typedef void (*hist_t)(const GpuMat& src, OutputArray hist, const GpuMat& levels, InputOutputArray buf, cudaStream_t stream); + static const hist_t hist_callers[] = + { + NppHistogramRangeC1::hist, + 0, + NppHistogramRangeC1::hist, + NppHistogramRangeC1::hist, + 0, + NppHistogramRangeC1::hist + }; + + GpuMat src = _src.getGpuMat(); + GpuMat levels = _levels.getGpuMat(); + + CV_Assert( src.type() == CV_8UC1 || src.type() == CV_16UC1 || src.type() == CV_16SC1 || src.type() == CV_32FC1 ); + + hist_callers[src.depth()](src, hist, levels, buf, StreamAccessor::getStream(stream)); +} + +void cv::gpu::histRange(InputArray _src, GpuMat hist[4], const GpuMat levels[4], InputOutputArray buf, Stream& stream) +{ + typedef void (*hist_t)(const GpuMat& src, GpuMat hist[4], const GpuMat levels[4], InputOutputArray buf, cudaStream_t stream); + static const hist_t hist_callers[] = + { + NppHistogramRangeC4::hist, + 0, + NppHistogramRangeC4::hist, + NppHistogramRangeC4::hist, + 0, + NppHistogramRangeC4::hist + }; + + GpuMat src = _src.getGpuMat(); + + CV_Assert( src.type() == CV_8UC4 || src.type() == CV_16UC4 || src.type() == CV_16SC4 || src.type() == CV_32FC4 ); + + hist_callers[src.depth()](src, hist, levels, buf, StreamAccessor::getStream(stream)); } #endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpuimgproc/src/hough.cpp b/modules/gpuimgproc/src/hough.cpp deleted file mode 100644 index 15e529762..000000000 --- a/modules/gpuimgproc/src/hough.cpp +++ /dev/null @@ -1,1432 +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" - -using namespace cv; -using namespace cv::gpu; - -#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) - -void cv::gpu::HoughLines(const GpuMat&, GpuMat&, float, float, int, bool, int) { throw_no_cuda(); } -void cv::gpu::HoughLines(const GpuMat&, GpuMat&, HoughLinesBuf&, float, float, int, bool, int) { throw_no_cuda(); } -void cv::gpu::HoughLinesDownload(const GpuMat&, OutputArray, OutputArray) { throw_no_cuda(); } - -void cv::gpu::HoughLinesP(const GpuMat&, GpuMat&, HoughLinesBuf&, float, float, int, int, int) { throw_no_cuda(); } - -void cv::gpu::HoughCircles(const GpuMat&, GpuMat&, int, float, float, int, int, int, int, int) { throw_no_cuda(); } -void cv::gpu::HoughCircles(const GpuMat&, GpuMat&, HoughCirclesBuf&, int, float, float, int, int, int, int, int) { throw_no_cuda(); } -void cv::gpu::HoughCirclesDownload(const GpuMat&, OutputArray) { throw_no_cuda(); } - -Ptr cv::gpu::GeneralizedHough_GPU::create(int) { throw_no_cuda(); return Ptr(); } -cv::gpu::GeneralizedHough_GPU::~GeneralizedHough_GPU() {} -void cv::gpu::GeneralizedHough_GPU::setTemplate(const GpuMat&, int, Point) { throw_no_cuda(); } -void cv::gpu::GeneralizedHough_GPU::setTemplate(const GpuMat&, const GpuMat&, const GpuMat&, Point) { throw_no_cuda(); } -void cv::gpu::GeneralizedHough_GPU::detect(const GpuMat&, GpuMat&, int) { throw_no_cuda(); } -void cv::gpu::GeneralizedHough_GPU::detect(const GpuMat&, const GpuMat&, const GpuMat&, GpuMat&) { throw_no_cuda(); } -void cv::gpu::GeneralizedHough_GPU::download(const GpuMat&, OutputArray, OutputArray) { throw_no_cuda(); } -void cv::gpu::GeneralizedHough_GPU::release() {} - -#else /* !defined (HAVE_CUDA) */ - -#include "opencv2/core/utility.hpp" - -namespace cv { namespace gpu { namespace cudev -{ - namespace hough - { - int buildPointList_gpu(PtrStepSzb src, unsigned int* list); - } -}}} - -////////////////////////////////////////////////////////// -// HoughLines - -namespace cv { namespace gpu { namespace cudev -{ - namespace hough - { - void linesAccum_gpu(const unsigned int* list, int count, PtrStepSzi accum, float rho, float theta, size_t sharedMemPerBlock, bool has20); - int linesGetResult_gpu(PtrStepSzi accum, float2* out, int* votes, int maxSize, float rho, float theta, int threshold, bool doSort); - } -}}} - -void cv::gpu::HoughLines(const GpuMat& src, GpuMat& lines, float rho, float theta, int threshold, bool doSort, int maxLines) -{ - HoughLinesBuf buf; - HoughLines(src, lines, buf, rho, theta, threshold, doSort, maxLines); -} - -void cv::gpu::HoughLines(const GpuMat& src, GpuMat& lines, HoughLinesBuf& buf, float rho, float theta, int threshold, bool doSort, int maxLines) -{ - using namespace cv::gpu::cudev::hough; - - CV_Assert(src.type() == CV_8UC1); - CV_Assert(src.cols < std::numeric_limits::max()); - CV_Assert(src.rows < std::numeric_limits::max()); - - ensureSizeIsEnough(1, src.size().area(), CV_32SC1, buf.list); - unsigned int* srcPoints = buf.list.ptr(); - - const int pointsCount = buildPointList_gpu(src, srcPoints); - if (pointsCount == 0) - { - lines.release(); - return; - } - - const int numangle = cvRound(CV_PI / theta); - const int numrho = cvRound(((src.cols + src.rows) * 2 + 1) / rho); - CV_Assert(numangle > 0 && numrho > 0); - - ensureSizeIsEnough(numangle + 2, numrho + 2, CV_32SC1, buf.accum); - buf.accum.setTo(Scalar::all(0)); - - DeviceInfo devInfo; - linesAccum_gpu(srcPoints, pointsCount, buf.accum, rho, theta, devInfo.sharedMemPerBlock(), devInfo.supports(FEATURE_SET_COMPUTE_20)); - - ensureSizeIsEnough(2, maxLines, CV_32FC2, lines); - - int linesCount = linesGetResult_gpu(buf.accum, lines.ptr(0), lines.ptr(1), maxLines, rho, theta, threshold, doSort); - if (linesCount > 0) - lines.cols = linesCount; - else - lines.release(); -} - -void cv::gpu::HoughLinesDownload(const GpuMat& d_lines, OutputArray h_lines_, OutputArray h_votes_) -{ - if (d_lines.empty()) - { - h_lines_.release(); - if (h_votes_.needed()) - h_votes_.release(); - return; - } - - CV_Assert(d_lines.rows == 2 && d_lines.type() == CV_32FC2); - - h_lines_.create(1, d_lines.cols, CV_32FC2); - Mat h_lines = h_lines_.getMat(); - d_lines.row(0).download(h_lines); - - if (h_votes_.needed()) - { - h_votes_.create(1, d_lines.cols, CV_32SC1); - Mat h_votes = h_votes_.getMat(); - GpuMat d_votes(1, d_lines.cols, CV_32SC1, const_cast(d_lines.ptr(1))); - d_votes.download(h_votes); - } -} - -////////////////////////////////////////////////////////// -// HoughLinesP - -namespace cv { namespace gpu { namespace cudev -{ - namespace hough - { - int houghLinesProbabilistic_gpu(PtrStepSzb mask, PtrStepSzi accum, int4* out, int maxSize, float rho, float theta, int lineGap, int lineLength); - } -}}} - -void cv::gpu::HoughLinesP(const GpuMat& src, GpuMat& lines, HoughLinesBuf& buf, float rho, float theta, int minLineLength, int maxLineGap, int maxLines) -{ - using namespace cv::gpu::cudev::hough; - - CV_Assert( src.type() == CV_8UC1 ); - CV_Assert( src.cols < std::numeric_limits::max() ); - CV_Assert( src.rows < std::numeric_limits::max() ); - - ensureSizeIsEnough(1, src.size().area(), CV_32SC1, buf.list); - unsigned int* srcPoints = buf.list.ptr(); - - const int pointsCount = buildPointList_gpu(src, srcPoints); - if (pointsCount == 0) - { - lines.release(); - return; - } - - const int numangle = cvRound(CV_PI / theta); - const int numrho = cvRound(((src.cols + src.rows) * 2 + 1) / rho); - CV_Assert( numangle > 0 && numrho > 0 ); - - ensureSizeIsEnough(numangle + 2, numrho + 2, CV_32SC1, buf.accum); - buf.accum.setTo(Scalar::all(0)); - - DeviceInfo devInfo; - linesAccum_gpu(srcPoints, pointsCount, buf.accum, rho, theta, devInfo.sharedMemPerBlock(), devInfo.supports(FEATURE_SET_COMPUTE_20)); - - ensureSizeIsEnough(1, maxLines, CV_32SC4, lines); - - int linesCount = houghLinesProbabilistic_gpu(src, buf.accum, lines.ptr(), maxLines, rho, theta, maxLineGap, minLineLength); - - if (linesCount > 0) - lines.cols = linesCount; - else - lines.release(); -} - -////////////////////////////////////////////////////////// -// HoughCircles - -namespace cv { namespace gpu { namespace cudev -{ - namespace hough - { - void circlesAccumCenters_gpu(const unsigned int* list, int count, PtrStepi dx, PtrStepi dy, PtrStepSzi accum, int minRadius, int maxRadius, float idp); - int buildCentersList_gpu(PtrStepSzi accum, unsigned int* centers, int threshold); - int circlesAccumRadius_gpu(const unsigned int* centers, int centersCount, const unsigned int* list, int count, - float3* circles, int maxCircles, float dp, int minRadius, int maxRadius, int threshold, bool has20); - } -}}} - -void cv::gpu::HoughCircles(const GpuMat& src, GpuMat& circles, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles) -{ - HoughCirclesBuf buf; - HoughCircles(src, circles, buf, method, dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius, maxCircles); -} - -void cv::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) -{ - using namespace cv::gpu::cudev::hough; - - CV_Assert(src.type() == CV_8UC1); - CV_Assert(src.cols < std::numeric_limits::max()); - CV_Assert(src.rows < std::numeric_limits::max()); - CV_Assert(method == cv::HOUGH_GRADIENT); - CV_Assert(dp > 0); - CV_Assert(minRadius > 0 && maxRadius > minRadius); - CV_Assert(cannyThreshold > 0); - CV_Assert(votesThreshold > 0); - CV_Assert(maxCircles > 0); - - const float idp = 1.0f / dp; - - cv::gpu::Canny(src, buf.cannyBuf, buf.edges, std::max(cannyThreshold / 2, 1), cannyThreshold); - - ensureSizeIsEnough(2, src.size().area(), CV_32SC1, buf.list); - unsigned int* srcPoints = buf.list.ptr(0); - unsigned int* centers = buf.list.ptr(1); - - const int pointsCount = buildPointList_gpu(buf.edges, srcPoints); - if (pointsCount == 0) - { - circles.release(); - return; - } - - ensureSizeIsEnough(cvCeil(src.rows * idp) + 2, cvCeil(src.cols * idp) + 2, CV_32SC1, buf.accum); - buf.accum.setTo(Scalar::all(0)); - - circlesAccumCenters_gpu(srcPoints, pointsCount, buf.cannyBuf.dx, buf.cannyBuf.dy, buf.accum, minRadius, maxRadius, idp); - - int centersCount = buildCentersList_gpu(buf.accum, centers, votesThreshold); - if (centersCount == 0) - { - circles.release(); - return; - } - - if (minDist > 1) - { - cv::AutoBuffer oldBuf_(centersCount); - cv::AutoBuffer newBuf_(centersCount); - int newCount = 0; - - ushort2* oldBuf = oldBuf_; - ushort2* newBuf = newBuf_; - - cudaSafeCall( cudaMemcpy(oldBuf, centers, centersCount * sizeof(ushort2), cudaMemcpyDeviceToHost) ); - - const int cellSize = cvRound(minDist); - const int gridWidth = (src.cols + cellSize - 1) / cellSize; - const int gridHeight = (src.rows + cellSize - 1) / cellSize; - - std::vector< std::vector > grid(gridWidth * gridHeight); - - const float minDist2 = minDist * minDist; - - for (int i = 0; i < centersCount; ++i) - { - ushort2 p = oldBuf[i]; - - bool good = true; - - int xCell = static_cast(p.x / cellSize); - int yCell = static_cast(p.y / cellSize); - - int x1 = xCell - 1; - int y1 = yCell - 1; - int x2 = xCell + 1; - int y2 = yCell + 1; - - // boundary check - x1 = std::max(0, x1); - y1 = std::max(0, y1); - x2 = std::min(gridWidth - 1, x2); - y2 = std::min(gridHeight - 1, y2); - - for (int yy = y1; yy <= y2; ++yy) - { - for (int xx = x1; xx <= x2; ++xx) - { - std::vector& m = grid[yy * gridWidth + xx]; - - for(size_t j = 0; j < m.size(); ++j) - { - float dx = (float)(p.x - m[j].x); - float dy = (float)(p.y - m[j].y); - - if (dx * dx + dy * dy < minDist2) - { - good = false; - goto break_out; - } - } - } - } - - break_out: - - if(good) - { - grid[yCell * gridWidth + xCell].push_back(p); - - newBuf[newCount++] = p; - } - } - - cudaSafeCall( cudaMemcpy(centers, newBuf, newCount * sizeof(unsigned int), cudaMemcpyHostToDevice) ); - centersCount = newCount; - } - - ensureSizeIsEnough(1, maxCircles, CV_32FC3, circles); - - const int circlesCount = circlesAccumRadius_gpu(centers, centersCount, srcPoints, pointsCount, circles.ptr(), maxCircles, - dp, minRadius, maxRadius, votesThreshold, deviceSupports(FEATURE_SET_COMPUTE_20)); - - if (circlesCount > 0) - circles.cols = circlesCount; - else - circles.release(); -} - -void cv::gpu::HoughCirclesDownload(const GpuMat& d_circles, cv::OutputArray h_circles_) -{ - if (d_circles.empty()) - { - h_circles_.release(); - return; - } - - CV_Assert(d_circles.rows == 1 && d_circles.type() == CV_32FC3); - - h_circles_.create(1, d_circles.cols, CV_32FC3); - Mat h_circles = h_circles_.getMat(); - d_circles.download(h_circles); -} - -////////////////////////////////////////////////////////// -// GeneralizedHough - -namespace cv { namespace gpu { namespace cudev -{ - namespace hough - { - template - int buildEdgePointList_gpu(PtrStepSzb edges, PtrStepSzb dx, PtrStepSzb dy, unsigned int* coordList, float* thetaList); - void buildRTable_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, - PtrStepSz r_table, int* r_sizes, - short2 templCenter, int levels); - - void GHT_Ballard_Pos_calcHist_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, - PtrStepSz r_table, const int* r_sizes, - PtrStepSzi hist, - float dp, int levels); - int GHT_Ballard_Pos_findPosInHist_gpu(PtrStepSzi hist, float4* out, int3* votes, int maxSize, float dp, int threshold); - - void GHT_Ballard_PosScale_calcHist_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, - PtrStepSz r_table, const int* r_sizes, - PtrStepi hist, int rows, int cols, - float minScale, float scaleStep, int scaleRange, - float dp, int levels); - int GHT_Ballard_PosScale_findPosInHist_gpu(PtrStepi hist, int rows, int cols, int scaleRange, float4* out, int3* votes, int maxSize, - float minScale, float scaleStep, float dp, int threshold); - - void GHT_Ballard_PosRotation_calcHist_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, - PtrStepSz r_table, const int* r_sizes, - PtrStepi hist, int rows, int cols, - float minAngle, float angleStep, int angleRange, - float dp, int levels); - int GHT_Ballard_PosRotation_findPosInHist_gpu(PtrStepi hist, int rows, int cols, int angleRange, float4* out, int3* votes, int maxSize, - float minAngle, float angleStep, float dp, int threshold); - - void GHT_Guil_Full_setTemplFeatures(PtrStepb p1_pos, PtrStepb p1_theta, PtrStepb p2_pos, PtrStepb d12, PtrStepb r1, PtrStepb r2); - void GHT_Guil_Full_setImageFeatures(PtrStepb p1_pos, PtrStepb p1_theta, PtrStepb p2_pos, PtrStepb d12, PtrStepb r1, PtrStepb r2); - void GHT_Guil_Full_buildTemplFeatureList_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, - int* sizes, int maxSize, - float xi, float angleEpsilon, int levels, - float2 center, float maxDist); - void GHT_Guil_Full_buildImageFeatureList_gpu(const unsigned int* coordList, const float* thetaList, int pointsCount, - int* sizes, int maxSize, - float xi, float angleEpsilon, int levels, - float2 center, float maxDist); - void GHT_Guil_Full_calcOHist_gpu(const int* templSizes, const int* imageSizes, int* OHist, - float minAngle, float maxAngle, float angleStep, int angleRange, - int levels, int tMaxSize); - void GHT_Guil_Full_calcSHist_gpu(const int* templSizes, const int* imageSizes, int* SHist, - float angle, float angleEpsilon, - float minScale, float maxScale, float iScaleStep, int scaleRange, - int levels, int tMaxSize); - void GHT_Guil_Full_calcPHist_gpu(const int* templSizes, const int* imageSizes, PtrStepSzi PHist, - float angle, float angleEpsilon, float scale, - float dp, - int levels, int tMaxSize); - int GHT_Guil_Full_findPosInHist_gpu(PtrStepSzi hist, float4* out, int3* votes, int curSize, int maxSize, - float angle, int angleVotes, float scale, int scaleVotes, - float dp, int threshold); - } -}}} - -namespace -{ - ///////////////////////////////////// - // Common - - template void releaseVector(std::vector& v) - { - std::vector empty; - empty.swap(v); - } - - class GHT_Pos : public GeneralizedHough_GPU - { - public: - GHT_Pos(); - - protected: - void setTemplateImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Point templCenter); - void detectImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, GpuMat& positions); - void releaseImpl(); - - virtual void processTempl() = 0; - virtual void processImage() = 0; - - void buildEdgePointList(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy); - void filterMinDist(); - void convertTo(GpuMat& positions); - - int maxSize; - double minDist; - - Size templSize; - Point templCenter; - GpuMat templEdges; - GpuMat templDx; - GpuMat templDy; - - Size imageSize; - GpuMat imageEdges; - GpuMat imageDx; - GpuMat imageDy; - - GpuMat edgePointList; - - GpuMat outBuf; - int posCount; - - std::vector oldPosBuf; - std::vector oldVoteBuf; - std::vector newPosBuf; - std::vector newVoteBuf; - std::vector indexies; - }; - - GHT_Pos::GHT_Pos() - { - maxSize = 10000; - minDist = 1.0; - } - - void GHT_Pos::setTemplateImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Point templCenter_) - { - templSize = edges.size(); - templCenter = templCenter_; - - ensureSizeIsEnough(templSize, edges.type(), templEdges); - ensureSizeIsEnough(templSize, dx.type(), templDx); - ensureSizeIsEnough(templSize, dy.type(), templDy); - - edges.copyTo(templEdges); - dx.copyTo(templDx); - dy.copyTo(templDy); - - processTempl(); - } - - void GHT_Pos::detectImpl(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, GpuMat& positions) - { - imageSize = edges.size(); - - ensureSizeIsEnough(imageSize, edges.type(), imageEdges); - ensureSizeIsEnough(imageSize, dx.type(), imageDx); - ensureSizeIsEnough(imageSize, dy.type(), imageDy); - - edges.copyTo(imageEdges); - dx.copyTo(imageDx); - dy.copyTo(imageDy); - - posCount = 0; - - processImage(); - - if (posCount == 0) - positions.release(); - else - { - if (minDist > 1) - filterMinDist(); - convertTo(positions); - } - } - - void GHT_Pos::releaseImpl() - { - templSize = Size(); - templCenter = Point(-1, -1); - templEdges.release(); - templDx.release(); - templDy.release(); - - imageSize = Size(); - imageEdges.release(); - imageDx.release(); - imageDy.release(); - - edgePointList.release(); - - outBuf.release(); - posCount = 0; - - releaseVector(oldPosBuf); - releaseVector(oldVoteBuf); - releaseVector(newPosBuf); - releaseVector(newVoteBuf); - releaseVector(indexies); - } - - void GHT_Pos::buildEdgePointList(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy) - { - using namespace cv::gpu::cudev::hough; - - typedef int (*func_t)(PtrStepSzb edges, PtrStepSzb dx, PtrStepSzb dy, unsigned int* coordList, float* thetaList); - static const func_t funcs[] = - { - 0, - 0, - 0, - buildEdgePointList_gpu, - buildEdgePointList_gpu, - buildEdgePointList_gpu, - 0 - }; - - CV_Assert(edges.type() == CV_8UC1); - CV_Assert(dx.size() == edges.size()); - CV_Assert(dy.type() == dx.type() && dy.size() == edges.size()); - - const func_t func = funcs[dx.depth()]; - CV_Assert(func != 0); - - edgePointList.cols = (int) (edgePointList.step / sizeof(int)); - ensureSizeIsEnough(2, edges.size().area(), CV_32SC1, edgePointList); - - edgePointList.cols = func(edges, dx, dy, edgePointList.ptr(0), edgePointList.ptr(1)); - } - - struct IndexCmp - { - const int3* aux; - - explicit IndexCmp(const int3* _aux) : aux(_aux) {} - - bool operator ()(int l1, int l2) const - { - return aux[l1].x > aux[l2].x; - } - }; - - void GHT_Pos::filterMinDist() - { - oldPosBuf.resize(posCount); - oldVoteBuf.resize(posCount); - - cudaSafeCall( cudaMemcpy(&oldPosBuf[0], outBuf.ptr(0), posCount * sizeof(float4), cudaMemcpyDeviceToHost) ); - cudaSafeCall( cudaMemcpy(&oldVoteBuf[0], outBuf.ptr(1), posCount * sizeof(int3), cudaMemcpyDeviceToHost) ); - - indexies.resize(posCount); - for (int i = 0; i < posCount; ++i) - indexies[i] = i; - std::sort(indexies.begin(), indexies.end(), IndexCmp(&oldVoteBuf[0])); - - newPosBuf.clear(); - newVoteBuf.clear(); - newPosBuf.reserve(posCount); - newVoteBuf.reserve(posCount); - - const int cellSize = cvRound(minDist); - const int gridWidth = (imageSize.width + cellSize - 1) / cellSize; - const int gridHeight = (imageSize.height + cellSize - 1) / cellSize; - - std::vector< std::vector > grid(gridWidth * gridHeight); - - const double minDist2 = minDist * minDist; - - for (int i = 0; i < posCount; ++i) - { - const int ind = indexies[i]; - - Point2f p(oldPosBuf[ind].x, oldPosBuf[ind].y); - - bool good = true; - - const int xCell = static_cast(p.x / cellSize); - const int yCell = static_cast(p.y / cellSize); - - int x1 = xCell - 1; - int y1 = yCell - 1; - int x2 = xCell + 1; - int y2 = yCell + 1; - - // boundary check - x1 = std::max(0, x1); - y1 = std::max(0, y1); - x2 = std::min(gridWidth - 1, x2); - y2 = std::min(gridHeight - 1, y2); - - for (int yy = y1; yy <= y2; ++yy) - { - for (int xx = x1; xx <= x2; ++xx) - { - const std::vector& m = grid[yy * gridWidth + xx]; - - for(size_t j = 0; j < m.size(); ++j) - { - const Point2f d = p - m[j]; - - if (d.ddot(d) < minDist2) - { - good = false; - goto break_out; - } - } - } - } - - break_out: - - if(good) - { - grid[yCell * gridWidth + xCell].push_back(p); - - newPosBuf.push_back(oldPosBuf[ind]); - newVoteBuf.push_back(oldVoteBuf[ind]); - } - } - - posCount = static_cast(newPosBuf.size()); - cudaSafeCall( cudaMemcpy(outBuf.ptr(0), &newPosBuf[0], posCount * sizeof(float4), cudaMemcpyHostToDevice) ); - cudaSafeCall( cudaMemcpy(outBuf.ptr(1), &newVoteBuf[0], posCount * sizeof(int3), cudaMemcpyHostToDevice) ); - } - - void GHT_Pos::convertTo(GpuMat& positions) - { - ensureSizeIsEnough(2, posCount, CV_32FC4, positions); - GpuMat(2, posCount, CV_32FC4, outBuf.data, outBuf.step).copyTo(positions); - } - - ///////////////////////////////////// - // POSITION Ballard - - class GHT_Ballard_Pos : public GHT_Pos - { - public: - AlgorithmInfo* info() const; - - GHT_Ballard_Pos(); - - protected: - void releaseImpl(); - - void processTempl(); - void processImage(); - - virtual void calcHist(); - virtual void findPosInHist(); - - int levels; - int votesThreshold; - double dp; - - GpuMat r_table; - GpuMat r_sizes; - - GpuMat hist; - }; - - CV_INIT_ALGORITHM(GHT_Ballard_Pos, "GeneralizedHough_GPU.POSITION", - obj.info()->addParam(obj, "maxSize", obj.maxSize, false, 0, 0, - "Maximal size of inner buffers."); - obj.info()->addParam(obj, "minDist", obj.minDist, false, 0, 0, - "Minimum distance between the centers of the detected objects."); - obj.info()->addParam(obj, "levels", obj.levels, false, 0, 0, - "R-Table levels."); - obj.info()->addParam(obj, "votesThreshold", obj.votesThreshold, false, 0, 0, - "The accumulator threshold for the template centers at the detection stage. The smaller it is, the more false positions may be detected."); - obj.info()->addParam(obj, "dp", obj.dp, false, 0, 0, - "Inverse ratio of the accumulator resolution to the image resolution.")); - - GHT_Ballard_Pos::GHT_Ballard_Pos() - { - levels = 360; - votesThreshold = 100; - dp = 1.0; - } - - void GHT_Ballard_Pos::releaseImpl() - { - GHT_Pos::releaseImpl(); - - r_table.release(); - r_sizes.release(); - - hist.release(); - } - - void GHT_Ballard_Pos::processTempl() - { - using namespace cv::gpu::cudev::hough; - - CV_Assert(levels > 0); - - buildEdgePointList(templEdges, templDx, templDy); - - ensureSizeIsEnough(levels + 1, maxSize, CV_16SC2, r_table); - ensureSizeIsEnough(1, levels + 1, CV_32SC1, r_sizes); - r_sizes.setTo(Scalar::all(0)); - - if (edgePointList.cols > 0) - { - buildRTable_gpu(edgePointList.ptr(0), edgePointList.ptr(1), edgePointList.cols, - r_table, r_sizes.ptr(), make_short2(templCenter.x, templCenter.y), levels); - gpu::min(r_sizes, maxSize, r_sizes); - } - } - - void GHT_Ballard_Pos::processImage() - { - calcHist(); - findPosInHist(); - } - - void GHT_Ballard_Pos::calcHist() - { - using namespace cv::gpu::cudev::hough; - - CV_Assert(levels > 0 && r_table.rows == (levels + 1) && r_sizes.cols == (levels + 1)); - CV_Assert(dp > 0.0); - - const double idp = 1.0 / dp; - - buildEdgePointList(imageEdges, imageDx, imageDy); - - ensureSizeIsEnough(cvCeil(imageSize.height * idp) + 2, cvCeil(imageSize.width * idp) + 2, CV_32SC1, hist); - hist.setTo(Scalar::all(0)); - - if (edgePointList.cols > 0) - { - GHT_Ballard_Pos_calcHist_gpu(edgePointList.ptr(0), edgePointList.ptr(1), edgePointList.cols, - r_table, r_sizes.ptr(), - hist, - (float)dp, levels); - } - } - - void GHT_Ballard_Pos::findPosInHist() - { - using namespace cv::gpu::cudev::hough; - - CV_Assert(votesThreshold > 0); - - ensureSizeIsEnough(2, maxSize, CV_32FC4, outBuf); - - posCount = GHT_Ballard_Pos_findPosInHist_gpu(hist, outBuf.ptr(0), outBuf.ptr(1), maxSize, (float)dp, votesThreshold); - } - - ///////////////////////////////////// - // POSITION & SCALE - - class GHT_Ballard_PosScale : public GHT_Ballard_Pos - { - public: - AlgorithmInfo* info() const; - - GHT_Ballard_PosScale(); - - protected: - void calcHist(); - void findPosInHist(); - - double minScale; - double maxScale; - double scaleStep; - }; - - CV_INIT_ALGORITHM(GHT_Ballard_PosScale, "GeneralizedHough_GPU.POSITION_SCALE", - obj.info()->addParam(obj, "maxSize", obj.maxSize, false, 0, 0, - "Maximal size of inner buffers."); - obj.info()->addParam(obj, "minDist", obj.minDist, false, 0, 0, - "Minimum distance between the centers of the detected objects."); - obj.info()->addParam(obj, "levels", obj.levels, false, 0, 0, - "R-Table levels."); - obj.info()->addParam(obj, "votesThreshold", obj.votesThreshold, false, 0, 0, - "The accumulator threshold for the template centers at the detection stage. The smaller it is, the more false positions may be detected."); - obj.info()->addParam(obj, "dp", obj.dp, false, 0, 0, - "Inverse ratio of the accumulator resolution to the image resolution."); - obj.info()->addParam(obj, "minScale", obj.minScale, false, 0, 0, - "Minimal scale to detect."); - obj.info()->addParam(obj, "maxScale", obj.maxScale, false, 0, 0, - "Maximal scale to detect."); - obj.info()->addParam(obj, "scaleStep", obj.scaleStep, false, 0, 0, - "Scale step.")); - - GHT_Ballard_PosScale::GHT_Ballard_PosScale() - { - minScale = 0.5; - maxScale = 2.0; - scaleStep = 0.05; - } - - void GHT_Ballard_PosScale::calcHist() - { - using namespace cv::gpu::cudev::hough; - - CV_Assert(levels > 0 && r_table.rows == (levels + 1) && r_sizes.cols == (levels + 1)); - CV_Assert(dp > 0.0); - CV_Assert(minScale > 0.0 && minScale < maxScale); - CV_Assert(scaleStep > 0.0); - - const double idp = 1.0 / dp; - const int scaleRange = cvCeil((maxScale - minScale) / scaleStep); - const int rows = cvCeil(imageSize.height * idp); - const int cols = cvCeil(imageSize.width * idp); - - buildEdgePointList(imageEdges, imageDx, imageDy); - - ensureSizeIsEnough((scaleRange + 2) * (rows + 2), cols + 2, CV_32SC1, hist); - hist.setTo(Scalar::all(0)); - - if (edgePointList.cols > 0) - { - GHT_Ballard_PosScale_calcHist_gpu(edgePointList.ptr(0), edgePointList.ptr(1), edgePointList.cols, - r_table, r_sizes.ptr(), - hist, rows, cols, - (float)minScale, (float)scaleStep, scaleRange, (float)dp, levels); - } - } - - void GHT_Ballard_PosScale::findPosInHist() - { - using namespace cv::gpu::cudev::hough; - - CV_Assert(votesThreshold > 0); - - const double idp = 1.0 / dp; - const int scaleRange = cvCeil((maxScale - minScale) / scaleStep); - const int rows = cvCeil(imageSize.height * idp); - const int cols = cvCeil(imageSize.width * idp); - - ensureSizeIsEnough(2, maxSize, CV_32FC4, outBuf); - - posCount = GHT_Ballard_PosScale_findPosInHist_gpu(hist, rows, cols, scaleRange, outBuf.ptr(0), outBuf.ptr(1), maxSize, (float)minScale, (float)scaleStep, (float)dp, votesThreshold); - } - - ///////////////////////////////////// - // POSITION & Rotation - - class GHT_Ballard_PosRotation : public GHT_Ballard_Pos - { - public: - AlgorithmInfo* info() const; - - GHT_Ballard_PosRotation(); - - protected: - void calcHist(); - void findPosInHist(); - - double minAngle; - double maxAngle; - double angleStep; - }; - - CV_INIT_ALGORITHM(GHT_Ballard_PosRotation, "GeneralizedHough_GPU.POSITION_ROTATION", - obj.info()->addParam(obj, "maxSize", obj.maxSize, false, 0, 0, - "Maximal size of inner buffers."); - obj.info()->addParam(obj, "minDist", obj.minDist, false, 0, 0, - "Minimum distance between the centers of the detected objects."); - obj.info()->addParam(obj, "levels", obj.levels, false, 0, 0, - "R-Table levels."); - obj.info()->addParam(obj, "votesThreshold", obj.votesThreshold, false, 0, 0, - "The accumulator threshold for the template centers at the detection stage. The smaller it is, the more false positions may be detected."); - obj.info()->addParam(obj, "dp", obj.dp, false, 0, 0, - "Inverse ratio of the accumulator resolution to the image resolution."); - obj.info()->addParam(obj, "minAngle", obj.minAngle, false, 0, 0, - "Minimal rotation angle to detect in degrees."); - obj.info()->addParam(obj, "maxAngle", obj.maxAngle, false, 0, 0, - "Maximal rotation angle to detect in degrees."); - obj.info()->addParam(obj, "angleStep", obj.angleStep, false, 0, 0, - "Angle step in degrees.")); - - GHT_Ballard_PosRotation::GHT_Ballard_PosRotation() - { - minAngle = 0.0; - maxAngle = 360.0; - angleStep = 1.0; - } - - void GHT_Ballard_PosRotation::calcHist() - { - using namespace cv::gpu::cudev::hough; - - CV_Assert(levels > 0 && r_table.rows == (levels + 1) && r_sizes.cols == (levels + 1)); - CV_Assert(dp > 0.0); - CV_Assert(minAngle >= 0.0 && minAngle < maxAngle && maxAngle <= 360.0); - CV_Assert(angleStep > 0.0 && angleStep < 360.0); - - const double idp = 1.0 / dp; - const int angleRange = cvCeil((maxAngle - minAngle) / angleStep); - const int rows = cvCeil(imageSize.height * idp); - const int cols = cvCeil(imageSize.width * idp); - - buildEdgePointList(imageEdges, imageDx, imageDy); - - ensureSizeIsEnough((angleRange + 2) * (rows + 2), cols + 2, CV_32SC1, hist); - hist.setTo(Scalar::all(0)); - - if (edgePointList.cols > 0) - { - GHT_Ballard_PosRotation_calcHist_gpu(edgePointList.ptr(0), edgePointList.ptr(1), edgePointList.cols, - r_table, r_sizes.ptr(), - hist, rows, cols, - (float)minAngle, (float)angleStep, angleRange, (float)dp, levels); - } - } - - void GHT_Ballard_PosRotation::findPosInHist() - { - using namespace cv::gpu::cudev::hough; - - CV_Assert(votesThreshold > 0); - - const double idp = 1.0 / dp; - const int angleRange = cvCeil((maxAngle - minAngle) / angleStep); - const int rows = cvCeil(imageSize.height * idp); - const int cols = cvCeil(imageSize.width * idp); - - ensureSizeIsEnough(2, maxSize, CV_32FC4, outBuf); - - posCount = GHT_Ballard_PosRotation_findPosInHist_gpu(hist, rows, cols, angleRange, outBuf.ptr(0), outBuf.ptr(1), maxSize, (float)minAngle, (float)angleStep, (float)dp, votesThreshold); - } - - ///////////////////////////////////////// - // POSITION & SCALE & ROTATION - - double toRad(double a) - { - return a * CV_PI / 180.0; - } - - double clampAngle(double a) - { - double res = a; - - while (res > 360.0) - res -= 360.0; - while (res < 0) - res += 360.0; - - return res; - } - - bool angleEq(double a, double b, double eps = 1.0) - { - return (fabs(clampAngle(a - b)) <= eps); - } - - class GHT_Guil_Full : public GHT_Pos - { - public: - AlgorithmInfo* info() const; - - GHT_Guil_Full(); - - protected: - void releaseImpl(); - - void processTempl(); - void processImage(); - - struct Feature - { - GpuMat p1_pos; - GpuMat p1_theta; - GpuMat p2_pos; - - GpuMat d12; - - GpuMat r1; - GpuMat r2; - - GpuMat sizes; - int maxSize; - - void create(int levels, int maxCapacity, bool isTempl); - void release(); - }; - - typedef void (*set_func_t)(PtrStepb p1_pos, PtrStepb p1_theta, PtrStepb p2_pos, PtrStepb d12, PtrStepb r1, PtrStepb r2); - typedef void (*build_func_t)(const unsigned int* coordList, const float* thetaList, int pointsCount, - int* sizes, int maxSize, - float xi, float angleEpsilon, int levels, - float2 center, float maxDist); - - void buildFeatureList(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Feature& features, - set_func_t set_func, build_func_t build_func, bool isTempl, Point2d center = Point2d()); - - void calcOrientation(); - void calcScale(double angle); - void calcPosition(double angle, int angleVotes, double scale, int scaleVotes); - - double xi; - int levels; - double angleEpsilon; - - double minAngle; - double maxAngle; - double angleStep; - int angleThresh; - - double minScale; - double maxScale; - double scaleStep; - int scaleThresh; - - double dp; - int posThresh; - - Feature templFeatures; - Feature imageFeatures; - - std::vector< std::pair > angles; - std::vector< std::pair > scales; - - GpuMat hist; - std::vector h_buf; - }; - - CV_INIT_ALGORITHM(GHT_Guil_Full, "GeneralizedHough_GPU.POSITION_SCALE_ROTATION", - obj.info()->addParam(obj, "minDist", obj.minDist, false, 0, 0, - "Minimum distance between the centers of the detected objects."); - obj.info()->addParam(obj, "maxSize", obj.maxSize, false, 0, 0, - "Maximal size of inner buffers."); - obj.info()->addParam(obj, "xi", obj.xi, false, 0, 0, - "Angle difference in degrees between two points in feature."); - obj.info()->addParam(obj, "levels", obj.levels, false, 0, 0, - "Feature table levels."); - obj.info()->addParam(obj, "angleEpsilon", obj.angleEpsilon, false, 0, 0, - "Maximal difference between angles that treated as equal."); - obj.info()->addParam(obj, "minAngle", obj.minAngle, false, 0, 0, - "Minimal rotation angle to detect in degrees."); - obj.info()->addParam(obj, "maxAngle", obj.maxAngle, false, 0, 0, - "Maximal rotation angle to detect in degrees."); - obj.info()->addParam(obj, "angleStep", obj.angleStep, false, 0, 0, - "Angle step in degrees."); - obj.info()->addParam(obj, "angleThresh", obj.angleThresh, false, 0, 0, - "Angle threshold."); - obj.info()->addParam(obj, "minScale", obj.minScale, false, 0, 0, - "Minimal scale to detect."); - obj.info()->addParam(obj, "maxScale", obj.maxScale, false, 0, 0, - "Maximal scale to detect."); - obj.info()->addParam(obj, "scaleStep", obj.scaleStep, false, 0, 0, - "Scale step."); - obj.info()->addParam(obj, "scaleThresh", obj.scaleThresh, false, 0, 0, - "Scale threshold."); - obj.info()->addParam(obj, "dp", obj.dp, false, 0, 0, - "Inverse ratio of the accumulator resolution to the image resolution."); - obj.info()->addParam(obj, "posThresh", obj.posThresh, false, 0, 0, - "Position threshold.")); - - GHT_Guil_Full::GHT_Guil_Full() - { - maxSize = 1000; - xi = 90.0; - levels = 360; - angleEpsilon = 1.0; - - minAngle = 0.0; - maxAngle = 360.0; - angleStep = 1.0; - angleThresh = 15000; - - minScale = 0.5; - maxScale = 2.0; - scaleStep = 0.05; - scaleThresh = 1000; - - dp = 1.0; - posThresh = 100; - } - - void GHT_Guil_Full::releaseImpl() - { - GHT_Pos::releaseImpl(); - - templFeatures.release(); - imageFeatures.release(); - - releaseVector(angles); - releaseVector(scales); - - hist.release(); - releaseVector(h_buf); - } - - void GHT_Guil_Full::processTempl() - { - using namespace cv::gpu::cudev::hough; - - buildFeatureList(templEdges, templDx, templDy, templFeatures, - GHT_Guil_Full_setTemplFeatures, GHT_Guil_Full_buildTemplFeatureList_gpu, - true, templCenter); - - h_buf.resize(templFeatures.sizes.cols); - cudaSafeCall( cudaMemcpy(&h_buf[0], templFeatures.sizes.data, h_buf.size() * sizeof(int), cudaMemcpyDeviceToHost) ); - templFeatures.maxSize = *max_element(h_buf.begin(), h_buf.end()); - } - - void GHT_Guil_Full::processImage() - { - using namespace cv::gpu::cudev::hough; - - CV_Assert(levels > 0); - CV_Assert(templFeatures.sizes.cols == levels + 1); - CV_Assert(minAngle >= 0.0 && minAngle < maxAngle && maxAngle <= 360.0); - CV_Assert(angleStep > 0.0 && angleStep < 360.0); - CV_Assert(angleThresh > 0); - CV_Assert(minScale > 0.0 && minScale < maxScale); - CV_Assert(scaleStep > 0.0); - CV_Assert(scaleThresh > 0); - CV_Assert(dp > 0.0); - CV_Assert(posThresh > 0); - - const double iAngleStep = 1.0 / angleStep; - const int angleRange = cvCeil((maxAngle - minAngle) * iAngleStep); - - const double iScaleStep = 1.0 / scaleStep; - const int scaleRange = cvCeil((maxScale - minScale) * iScaleStep); - - const double idp = 1.0 / dp; - const int histRows = cvCeil(imageSize.height * idp); - const int histCols = cvCeil(imageSize.width * idp); - - ensureSizeIsEnough(histRows + 2, std::max(angleRange + 1, std::max(scaleRange + 1, histCols + 2)), CV_32SC1, hist); - h_buf.resize(std::max(angleRange + 1, scaleRange + 1)); - - ensureSizeIsEnough(2, maxSize, CV_32FC4, outBuf); - - buildFeatureList(imageEdges, imageDx, imageDy, imageFeatures, - GHT_Guil_Full_setImageFeatures, GHT_Guil_Full_buildImageFeatureList_gpu, - false); - - calcOrientation(); - - for (size_t i = 0; i < angles.size(); ++i) - { - const double angle = angles[i].first; - const int angleVotes = angles[i].second; - - calcScale(angle); - - for (size_t j = 0; j < scales.size(); ++j) - { - const double scale = scales[j].first; - const int scaleVotes = scales[j].second; - - calcPosition(angle, angleVotes, scale, scaleVotes); - } - } - } - - void GHT_Guil_Full::Feature::create(int levels, int maxCapacity, bool isTempl) - { - if (!isTempl) - { - ensureSizeIsEnough(levels + 1, maxCapacity, CV_32FC2, p1_pos); - ensureSizeIsEnough(levels + 1, maxCapacity, CV_32FC2, p2_pos); - } - - ensureSizeIsEnough(levels + 1, maxCapacity, CV_32FC1, p1_theta); - - ensureSizeIsEnough(levels + 1, maxCapacity, CV_32FC1, d12); - - if (isTempl) - { - ensureSizeIsEnough(levels + 1, maxCapacity, CV_32FC2, r1); - ensureSizeIsEnough(levels + 1, maxCapacity, CV_32FC2, r2); - } - - ensureSizeIsEnough(1, levels + 1, CV_32SC1, sizes); - sizes.setTo(Scalar::all(0)); - - maxSize = 0; - } - - void GHT_Guil_Full::Feature::release() - { - p1_pos.release(); - p1_theta.release(); - p2_pos.release(); - - d12.release(); - - r1.release(); - r2.release(); - - sizes.release(); - - maxSize = 0; - } - - void GHT_Guil_Full::buildFeatureList(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Feature& features, - set_func_t set_func, build_func_t build_func, bool isTempl, Point2d center) - { - CV_Assert(levels > 0); - - const double maxDist = sqrt((double) templSize.width * templSize.width + templSize.height * templSize.height) * maxScale; - - features.create(levels, maxSize, isTempl); - set_func(features.p1_pos, features.p1_theta, features.p2_pos, features.d12, features.r1, features.r2); - - buildEdgePointList(edges, dx, dy); - - if (edgePointList.cols > 0) - { - build_func(edgePointList.ptr(0), edgePointList.ptr(1), edgePointList.cols, - features.sizes.ptr(), maxSize, (float)xi, (float)angleEpsilon, levels, make_float2((float)center.x, (float)center.y), (float)maxDist); - } - } - - void GHT_Guil_Full::calcOrientation() - { - using namespace cv::gpu::cudev::hough; - - const double iAngleStep = 1.0 / angleStep; - const int angleRange = cvCeil((maxAngle - minAngle) * iAngleStep); - - hist.setTo(Scalar::all(0)); - GHT_Guil_Full_calcOHist_gpu(templFeatures.sizes.ptr(), imageFeatures.sizes.ptr(0), - hist.ptr(), (float)minAngle, (float)maxAngle, (float)angleStep, angleRange, levels, templFeatures.maxSize); - cudaSafeCall( cudaMemcpy(&h_buf[0], hist.data, h_buf.size() * sizeof(int), cudaMemcpyDeviceToHost) ); - - angles.clear(); - - for (int n = 0; n < angleRange; ++n) - { - if (h_buf[n] >= angleThresh) - { - const double angle = minAngle + n * angleStep; - angles.push_back(std::make_pair(angle, h_buf[n])); - } - } - } - - void GHT_Guil_Full::calcScale(double angle) - { - using namespace cv::gpu::cudev::hough; - - const double iScaleStep = 1.0 / scaleStep; - const int scaleRange = cvCeil((maxScale - minScale) * iScaleStep); - - hist.setTo(Scalar::all(0)); - GHT_Guil_Full_calcSHist_gpu(templFeatures.sizes.ptr(), imageFeatures.sizes.ptr(0), - hist.ptr(), (float)angle, (float)angleEpsilon, (float)minScale, (float)maxScale, (float)iScaleStep, scaleRange, levels, templFeatures.maxSize); - cudaSafeCall( cudaMemcpy(&h_buf[0], hist.data, h_buf.size() * sizeof(int), cudaMemcpyDeviceToHost) ); - - scales.clear(); - - for (int s = 0; s < scaleRange; ++s) - { - if (h_buf[s] >= scaleThresh) - { - const double scale = minScale + s * scaleStep; - scales.push_back(std::make_pair(scale, h_buf[s])); - } - } - } - - void GHT_Guil_Full::calcPosition(double angle, int angleVotes, double scale, int scaleVotes) - { - using namespace cv::gpu::cudev::hough; - - hist.setTo(Scalar::all(0)); - GHT_Guil_Full_calcPHist_gpu(templFeatures.sizes.ptr(), imageFeatures.sizes.ptr(0), - hist,(float) (float)angle, (float)angleEpsilon, (float)scale, (float)dp, levels, templFeatures.maxSize); - - posCount = GHT_Guil_Full_findPosInHist_gpu(hist, outBuf.ptr(0), outBuf.ptr(1), - posCount, maxSize, (float)angle, angleVotes, (float)scale, scaleVotes, (float)dp, posThresh); - } -} - -Ptr cv::gpu::GeneralizedHough_GPU::create(int method) -{ - switch (method) - { - case cv::GeneralizedHough::GHT_POSITION: - CV_Assert( !GHT_Ballard_Pos_info_auto.name().empty() ); - return new GHT_Ballard_Pos(); - - case (cv::GeneralizedHough::GHT_POSITION | cv::GeneralizedHough::GHT_SCALE): - CV_Assert( !GHT_Ballard_PosScale_info_auto.name().empty() ); - return new GHT_Ballard_PosScale(); - - case (cv::GeneralizedHough::GHT_POSITION | cv::GeneralizedHough::GHT_ROTATION): - CV_Assert( !GHT_Ballard_PosRotation_info_auto.name().empty() ); - return new GHT_Ballard_PosRotation(); - - case (cv::GeneralizedHough::GHT_POSITION | cv::GeneralizedHough::GHT_SCALE | cv::GeneralizedHough::GHT_ROTATION): - CV_Assert( !GHT_Guil_Full_info_auto.name().empty() ); - return new GHT_Guil_Full(); - } - - CV_Error(cv::Error::StsBadArg, "Unsupported method"); - return Ptr(); -} - -cv::gpu::GeneralizedHough_GPU::~GeneralizedHough_GPU() -{ -} - -void cv::gpu::GeneralizedHough_GPU::setTemplate(const GpuMat& templ, int cannyThreshold, Point templCenter) -{ - CV_Assert(templ.type() == CV_8UC1); - CV_Assert(cannyThreshold > 0); - - ensureSizeIsEnough(templ.size(), CV_8UC1, edges_); - Canny(templ, cannyBuf_, edges_, cannyThreshold / 2, cannyThreshold); - - if (templCenter == Point(-1, -1)) - templCenter = Point(templ.cols / 2, templ.rows / 2); - - setTemplateImpl(edges_, cannyBuf_.dx, cannyBuf_.dy, templCenter); -} - -void cv::gpu::GeneralizedHough_GPU::setTemplate(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Point templCenter) -{ - if (templCenter == Point(-1, -1)) - templCenter = Point(edges.cols / 2, edges.rows / 2); - - setTemplateImpl(edges, dx, dy, templCenter); -} - -void cv::gpu::GeneralizedHough_GPU::detect(const GpuMat& image, GpuMat& positions, int cannyThreshold) -{ - CV_Assert(image.type() == CV_8UC1); - CV_Assert(cannyThreshold > 0); - - ensureSizeIsEnough(image.size(), CV_8UC1, edges_); - Canny(image, cannyBuf_, edges_, cannyThreshold / 2, cannyThreshold); - - detectImpl(edges_, cannyBuf_.dx, cannyBuf_.dy, positions); -} - -void cv::gpu::GeneralizedHough_GPU::detect(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, GpuMat& positions) -{ - detectImpl(edges, dx, dy, positions); -} - -void cv::gpu::GeneralizedHough_GPU::download(const GpuMat& d_positions, OutputArray h_positions_, OutputArray h_votes_) -{ - if (d_positions.empty()) - { - h_positions_.release(); - if (h_votes_.needed()) - h_votes_.release(); - return; - } - - CV_Assert(d_positions.rows == 2 && d_positions.type() == CV_32FC4); - - h_positions_.create(1, d_positions.cols, CV_32FC4); - Mat h_positions = h_positions_.getMat(); - d_positions.row(0).download(h_positions); - - if (h_votes_.needed()) - { - h_votes_.create(1, d_positions.cols, CV_32SC3); - Mat h_votes = h_votes_.getMat(); - GpuMat d_votes(1, d_positions.cols, CV_32SC3, const_cast(d_positions.ptr(1))); - d_votes.download(h_votes); - } -} - -void cv::gpu::GeneralizedHough_GPU::release() -{ - edges_.release(); - cannyBuf_.release(); - releaseImpl(); -} - -#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpuimgproc/src/hough_circles.cpp b/modules/gpuimgproc/src/hough_circles.cpp new file mode 100644 index 000000000..f123cf579 --- /dev/null +++ b/modules/gpuimgproc/src/hough_circles.cpp @@ -0,0 +1,297 @@ +/*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; + +#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) || !defined(HAVE_OPENCV_GPUFILTERS) + +Ptr cv::gpu::createHoughCirclesDetector(float, float, int, int, int, int, int) { throw_no_cuda(); return Ptr(); } + +#else /* !defined (HAVE_CUDA) */ + +namespace cv { namespace gpu { namespace cudev +{ + namespace hough + { + int buildPointList_gpu(PtrStepSzb src, unsigned int* list); + } + + namespace hough_circles + { + void circlesAccumCenters_gpu(const unsigned int* list, int count, PtrStepi dx, PtrStepi dy, PtrStepSzi accum, int minRadius, int maxRadius, float idp); + int buildCentersList_gpu(PtrStepSzi accum, unsigned int* centers, int threshold); + int circlesAccumRadius_gpu(const unsigned int* centers, int centersCount, const unsigned int* list, int count, + float3* circles, int maxCircles, float dp, int minRadius, int maxRadius, int threshold, bool has20); + } +}}} + +namespace +{ + class HoughCirclesDetectorImpl : public HoughCirclesDetector + { + public: + HoughCirclesDetectorImpl(float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles); + + void detect(InputArray src, OutputArray circles); + + void setDp(float dp) { dp_ = dp; } + float getDp() const { return dp_; } + + void setMinDist(float minDist) { minDist_ = minDist; } + float getMinDist() const { return minDist_; } + + void setCannyThreshold(int cannyThreshold) { cannyThreshold_ = cannyThreshold; } + int getCannyThreshold() const { return cannyThreshold_; } + + void setVotesThreshold(int votesThreshold) { votesThreshold_ = votesThreshold; } + int getVotesThreshold() const { return votesThreshold_; } + + void setMinRadius(int minRadius) { minRadius_ = minRadius; } + int getMinRadius() const { return minRadius_; } + + void setMaxRadius(int maxRadius) { maxRadius_ = maxRadius; } + int getMaxRadius() const { return maxRadius_; } + + void setMaxCircles(int maxCircles) { maxCircles_ = maxCircles; } + int getMaxCircles() const { return maxCircles_; } + + void write(FileStorage& fs) const + { + fs << "name" << "HoughCirclesDetector_GPU" + << "dp" << dp_ + << "minDist" << minDist_ + << "cannyThreshold" << cannyThreshold_ + << "votesThreshold" << votesThreshold_ + << "minRadius" << minRadius_ + << "maxRadius" << maxRadius_ + << "maxCircles" << maxCircles_; + } + + void read(const FileNode& fn) + { + CV_Assert( String(fn["name"]) == "HoughCirclesDetector_GPU" ); + dp_ = (float)fn["dp"]; + minDist_ = (float)fn["minDist"]; + cannyThreshold_ = (int)fn["cannyThreshold"]; + votesThreshold_ = (int)fn["votesThreshold"]; + minRadius_ = (int)fn["minRadius"]; + maxRadius_ = (int)fn["maxRadius"]; + maxCircles_ = (int)fn["maxCircles"]; + } + + private: + float dp_; + float minDist_; + int cannyThreshold_; + int votesThreshold_; + int minRadius_; + int maxRadius_; + int maxCircles_; + + GpuMat dx_, dy_; + GpuMat edges_; + GpuMat accum_; + GpuMat list_; + GpuMat result_; + Ptr filterDx_; + Ptr filterDy_; + Ptr canny_; + }; + + HoughCirclesDetectorImpl::HoughCirclesDetectorImpl(float dp, float minDist, int cannyThreshold, int votesThreshold, + int minRadius, int maxRadius, int maxCircles) : + dp_(dp), minDist_(minDist), cannyThreshold_(cannyThreshold), votesThreshold_(votesThreshold), + minRadius_(minRadius), maxRadius_(maxRadius), maxCircles_(maxCircles) + { + canny_ = gpu::createCannyEdgeDetector(std::max(cannyThreshold_ / 2, 1), cannyThreshold_); + + filterDx_ = gpu::createSobelFilter(CV_8UC1, CV_32S, 1, 0); + filterDy_ = gpu::createSobelFilter(CV_8UC1, CV_32S, 0, 1); + } + + void HoughCirclesDetectorImpl::detect(InputArray _src, OutputArray circles) + { + using namespace cv::gpu::cudev::hough; + using namespace cv::gpu::cudev::hough_circles; + + GpuMat src = _src.getGpuMat(); + + CV_Assert( src.type() == CV_8UC1 ); + CV_Assert( src.cols < std::numeric_limits::max() ); + CV_Assert( src.rows < std::numeric_limits::max() ); + CV_Assert( dp_ > 0 ); + CV_Assert( minRadius_ > 0 && maxRadius_ > minRadius_ ); + CV_Assert( cannyThreshold_ > 0 ); + CV_Assert( votesThreshold_ > 0 ); + CV_Assert( maxCircles_ > 0 ); + + const float idp = 1.0f / dp_; + + filterDx_->apply(src, dx_); + filterDy_->apply(src, dy_); + + canny_->setLowThreshold(std::max(cannyThreshold_ / 2, 1)); + canny_->setHighThreshold(cannyThreshold_); + + canny_->detect(dx_, dy_, edges_); + + ensureSizeIsEnough(2, src.size().area(), CV_32SC1, list_); + unsigned int* srcPoints = list_.ptr(0); + unsigned int* centers = list_.ptr(1); + + const int pointsCount = buildPointList_gpu(edges_, srcPoints); + if (pointsCount == 0) + { + circles.release(); + return; + } + + ensureSizeIsEnough(cvCeil(src.rows * idp) + 2, cvCeil(src.cols * idp) + 2, CV_32SC1, accum_); + accum_.setTo(Scalar::all(0)); + + circlesAccumCenters_gpu(srcPoints, pointsCount, dx_, dy_, accum_, minRadius_, maxRadius_, idp); + + int centersCount = buildCentersList_gpu(accum_, centers, votesThreshold_); + if (centersCount == 0) + { + circles.release(); + return; + } + + if (minDist_ > 1) + { + AutoBuffer oldBuf_(centersCount); + AutoBuffer newBuf_(centersCount); + int newCount = 0; + + ushort2* oldBuf = oldBuf_; + ushort2* newBuf = newBuf_; + + cudaSafeCall( cudaMemcpy(oldBuf, centers, centersCount * sizeof(ushort2), cudaMemcpyDeviceToHost) ); + + const int cellSize = cvRound(minDist_); + const int gridWidth = (src.cols + cellSize - 1) / cellSize; + const int gridHeight = (src.rows + cellSize - 1) / cellSize; + + std::vector< std::vector > grid(gridWidth * gridHeight); + + const float minDist2 = minDist_ * minDist_; + + for (int i = 0; i < centersCount; ++i) + { + ushort2 p = oldBuf[i]; + + bool good = true; + + int xCell = static_cast(p.x / cellSize); + int yCell = static_cast(p.y / cellSize); + + int x1 = xCell - 1; + int y1 = yCell - 1; + int x2 = xCell + 1; + int y2 = yCell + 1; + + // boundary check + x1 = std::max(0, x1); + y1 = std::max(0, y1); + x2 = std::min(gridWidth - 1, x2); + y2 = std::min(gridHeight - 1, y2); + + for (int yy = y1; yy <= y2; ++yy) + { + for (int xx = x1; xx <= x2; ++xx) + { + std::vector& m = grid[yy * gridWidth + xx]; + + for(size_t j = 0; j < m.size(); ++j) + { + float dx = (float)(p.x - m[j].x); + float dy = (float)(p.y - m[j].y); + + if (dx * dx + dy * dy < minDist2) + { + good = false; + goto break_out; + } + } + } + } + + break_out: + + if(good) + { + grid[yCell * gridWidth + xCell].push_back(p); + + newBuf[newCount++] = p; + } + } + + cudaSafeCall( cudaMemcpy(centers, newBuf, newCount * sizeof(unsigned int), cudaMemcpyHostToDevice) ); + centersCount = newCount; + } + + ensureSizeIsEnough(1, maxCircles_, CV_32FC3, result_); + + int circlesCount = circlesAccumRadius_gpu(centers, centersCount, srcPoints, pointsCount, result_.ptr(), maxCircles_, + dp_, minRadius_, maxRadius_, votesThreshold_, deviceSupports(FEATURE_SET_COMPUTE_20)); + + if (circlesCount == 0) + { + circles.release(); + return; + } + + result_.cols = circlesCount; + result_.copyTo(circles); + } +} + +Ptr cv::gpu::createHoughCirclesDetector(float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles) +{ + return makePtr(dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius, maxCircles); +} + +#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpuimgproc/src/hough_lines.cpp b/modules/gpuimgproc/src/hough_lines.cpp new file mode 100644 index 000000000..e3e03cba7 --- /dev/null +++ b/modules/gpuimgproc/src/hough_lines.cpp @@ -0,0 +1,202 @@ +/*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; + +#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) + +Ptr cv::gpu::createHoughLinesDetector(float, float, int, bool, int) { throw_no_cuda(); return Ptr(); } + +#else /* !defined (HAVE_CUDA) */ + +namespace cv { namespace gpu { namespace cudev +{ + namespace hough + { + int buildPointList_gpu(PtrStepSzb src, unsigned int* list); + } + + namespace hough_lines + { + void linesAccum_gpu(const unsigned int* list, int count, PtrStepSzi accum, float rho, float theta, size_t sharedMemPerBlock, bool has20); + int linesGetResult_gpu(PtrStepSzi accum, float2* out, int* votes, int maxSize, float rho, float theta, int threshold, bool doSort); + } +}}} + +namespace +{ + class HoughLinesDetectorImpl : public HoughLinesDetector + { + public: + HoughLinesDetectorImpl(float rho, float theta, int threshold, bool doSort, int maxLines) : + rho_(rho), theta_(theta), threshold_(threshold), doSort_(doSort), maxLines_(maxLines) + { + } + + void detect(InputArray src, OutputArray lines); + void downloadResults(InputArray d_lines, OutputArray h_lines, OutputArray h_votes = noArray()); + + void setRho(float rho) { rho_ = rho; } + float getRho() const { return rho_; } + + void setTheta(float theta) { theta_ = theta; } + float getTheta() const { return theta_; } + + void setThreshold(int threshold) { threshold_ = threshold; } + int getThreshold() const { return threshold_; } + + void setDoSort(bool doSort) { doSort_ = doSort; } + bool getDoSort() const { return doSort_; } + + void setMaxLines(int maxLines) { maxLines_ = maxLines; } + int getMaxLines() const { return maxLines_; } + + void write(FileStorage& fs) const + { + fs << "name" << "HoughLinesDetector_GPU" + << "rho" << rho_ + << "theta" << theta_ + << "threshold" << threshold_ + << "doSort" << doSort_ + << "maxLines" << maxLines_; + } + + void read(const FileNode& fn) + { + CV_Assert( String(fn["name"]) == "HoughLinesDetector_GPU" ); + rho_ = (float)fn["rho"]; + theta_ = (float)fn["theta"]; + threshold_ = (int)fn["threshold"]; + doSort_ = (int)fn["doSort"] != 0; + maxLines_ = (int)fn["maxLines"]; + } + + private: + float rho_; + float theta_; + int threshold_; + bool doSort_; + int maxLines_; + + GpuMat accum_; + GpuMat list_; + GpuMat result_; + }; + + void HoughLinesDetectorImpl::detect(InputArray _src, OutputArray lines) + { + using namespace cv::gpu::cudev::hough; + using namespace cv::gpu::cudev::hough_lines; + + GpuMat src = _src.getGpuMat(); + + CV_Assert( src.type() == CV_8UC1 ); + CV_Assert( src.cols < std::numeric_limits::max() ); + CV_Assert( src.rows < std::numeric_limits::max() ); + + ensureSizeIsEnough(1, src.size().area(), CV_32SC1, list_); + unsigned int* srcPoints = list_.ptr(); + + const int pointsCount = buildPointList_gpu(src, srcPoints); + if (pointsCount == 0) + { + lines.release(); + return; + } + + const int numangle = cvRound(CV_PI / theta_); + const int numrho = cvRound(((src.cols + src.rows) * 2 + 1) / rho_); + CV_Assert( numangle > 0 && numrho > 0 ); + + ensureSizeIsEnough(numangle + 2, numrho + 2, CV_32SC1, accum_); + accum_.setTo(Scalar::all(0)); + + DeviceInfo devInfo; + linesAccum_gpu(srcPoints, pointsCount, accum_, rho_, theta_, devInfo.sharedMemPerBlock(), devInfo.supports(FEATURE_SET_COMPUTE_20)); + + ensureSizeIsEnough(2, maxLines_, CV_32FC2, result_); + + int linesCount = linesGetResult_gpu(accum_, result_.ptr(0), result_.ptr(1), maxLines_, rho_, theta_, threshold_, doSort_); + + if (linesCount == 0) + { + lines.release(); + return; + } + + result_.cols = linesCount; + result_.copyTo(lines); + } + + void HoughLinesDetectorImpl::downloadResults(InputArray _d_lines, OutputArray h_lines, OutputArray h_votes) + { + GpuMat d_lines = _d_lines.getGpuMat(); + + if (d_lines.empty()) + { + h_lines.release(); + if (h_votes.needed()) + h_votes.release(); + return; + } + + CV_Assert( d_lines.rows == 2 && d_lines.type() == CV_32FC2 ); + + d_lines.row(0).download(h_lines); + + if (h_votes.needed()) + { + GpuMat d_votes(1, d_lines.cols, CV_32SC1, d_lines.ptr(1)); + d_votes.download(h_votes); + } + } +} + +Ptr cv::gpu::createHoughLinesDetector(float rho, float theta, int threshold, bool doSort, int maxLines) +{ + return makePtr(rho, theta, threshold, doSort, maxLines); +} + +#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpuimgproc/src/hough_segments.cpp b/modules/gpuimgproc/src/hough_segments.cpp new file mode 100644 index 000000000..6f888a2c0 --- /dev/null +++ b/modules/gpuimgproc/src/hough_segments.cpp @@ -0,0 +1,183 @@ +/*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; + +#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) + +Ptr cv::gpu::createHoughSegmentDetector(float, float, int, int, int) { throw_no_cuda(); return Ptr(); } + +#else /* !defined (HAVE_CUDA) */ + +namespace cv { namespace gpu { namespace cudev +{ + namespace hough + { + int buildPointList_gpu(PtrStepSzb src, unsigned int* list); + } + + namespace hough_lines + { + void linesAccum_gpu(const unsigned int* list, int count, PtrStepSzi accum, float rho, float theta, size_t sharedMemPerBlock, bool has20); + } + + namespace hough_segments + { + int houghLinesProbabilistic_gpu(PtrStepSzb mask, PtrStepSzi accum, int4* out, int maxSize, float rho, float theta, int lineGap, int lineLength); + } +}}} + +namespace +{ + class HoughSegmentDetectorImpl : public HoughSegmentDetector + { + public: + HoughSegmentDetectorImpl(float rho, float theta, int minLineLength, int maxLineGap, int maxLines) : + rho_(rho), theta_(theta), minLineLength_(minLineLength), maxLineGap_(maxLineGap), maxLines_(maxLines) + { + } + + void detect(InputArray src, OutputArray lines); + + void setRho(float rho) { rho_ = rho; } + float getRho() const { return rho_; } + + void setTheta(float theta) { theta_ = theta; } + float getTheta() const { return theta_; } + + void setMinLineLength(int minLineLength) { minLineLength_ = minLineLength; } + int getMinLineLength() const { return minLineLength_; } + + void setMaxLineGap(int maxLineGap) { maxLineGap_ = maxLineGap; } + int getMaxLineGap() const { return maxLineGap_; } + + void setMaxLines(int maxLines) { maxLines_ = maxLines; } + int getMaxLines() const { return maxLines_; } + + void write(FileStorage& fs) const + { + fs << "name" << "PHoughLinesDetector_GPU" + << "rho" << rho_ + << "theta" << theta_ + << "minLineLength" << minLineLength_ + << "maxLineGap" << maxLineGap_ + << "maxLines" << maxLines_; + } + + void read(const FileNode& fn) + { + CV_Assert( String(fn["name"]) == "PHoughLinesDetector_GPU" ); + rho_ = (float)fn["rho"]; + theta_ = (float)fn["theta"]; + minLineLength_ = (int)fn["minLineLength"]; + maxLineGap_ = (int)fn["maxLineGap"]; + maxLines_ = (int)fn["maxLines"]; + } + + private: + float rho_; + float theta_; + int minLineLength_; + int maxLineGap_; + int maxLines_; + + GpuMat accum_; + GpuMat list_; + GpuMat result_; + }; + + void HoughSegmentDetectorImpl::detect(InputArray _src, OutputArray lines) + { + using namespace cv::gpu::cudev::hough; + using namespace cv::gpu::cudev::hough_lines; + using namespace cv::gpu::cudev::hough_segments; + + GpuMat src = _src.getGpuMat(); + + CV_Assert( src.type() == CV_8UC1 ); + CV_Assert( src.cols < std::numeric_limits::max() ); + CV_Assert( src.rows < std::numeric_limits::max() ); + + ensureSizeIsEnough(1, src.size().area(), CV_32SC1, list_); + unsigned int* srcPoints = list_.ptr(); + + const int pointsCount = buildPointList_gpu(src, srcPoints); + if (pointsCount == 0) + { + lines.release(); + return; + } + + const int numangle = cvRound(CV_PI / theta_); + const int numrho = cvRound(((src.cols + src.rows) * 2 + 1) / rho_); + CV_Assert( numangle > 0 && numrho > 0 ); + + ensureSizeIsEnough(numangle + 2, numrho + 2, CV_32SC1, accum_); + accum_.setTo(Scalar::all(0)); + + DeviceInfo devInfo; + linesAccum_gpu(srcPoints, pointsCount, accum_, rho_, theta_, devInfo.sharedMemPerBlock(), devInfo.supports(FEATURE_SET_COMPUTE_20)); + + ensureSizeIsEnough(1, maxLines_, CV_32SC4, result_); + + int linesCount = houghLinesProbabilistic_gpu(src, accum_, result_.ptr(), maxLines_, rho_, theta_, maxLineGap_, minLineLength_); + + if (linesCount == 0) + { + lines.release(); + return; + } + + result_.cols = linesCount; + result_.copyTo(lines); + } +} + +Ptr cv::gpu::createHoughSegmentDetector(float rho, float theta, int minLineLength, int maxLineGap, int maxLines) +{ + return makePtr(rho, theta, minLineLength, maxLineGap, maxLines); +} + +#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpuimgproc/src/match_template.cpp b/modules/gpuimgproc/src/match_template.cpp index 059d41ca9..aeebd01d9 100644 --- a/modules/gpuimgproc/src/match_template.cpp +++ b/modules/gpuimgproc/src/match_template.cpp @@ -47,7 +47,7 @@ using namespace cv::gpu; #if !defined (HAVE_CUDA) || !defined (HAVE_OPENCV_GPUARITHM) || defined (CUDA_DISABLER) -void cv::gpu::matchTemplate(const GpuMat&, const GpuMat&, GpuMat&, int, Stream&) { throw_no_cuda(); } +Ptr cv::gpu::createTemplateMatching(int, int, Size) { throw_no_cuda(); return Ptr(); } #else @@ -137,11 +137,8 @@ namespace cv { namespace gpu { namespace cudev } }}} -using namespace ::cv::gpu::cudev::match_template; - namespace { - // Evaluates optimal template's area threshold. If // template's area is less than the threshold, we use naive match // template version, otherwise FFT-based (if available) @@ -149,135 +146,317 @@ namespace { switch (method) { - case cv::TM_CCORR: + case TM_CCORR: if (depth == CV_32F) return 250; if (depth == CV_8U) return 300; break; - case cv::TM_SQDIFF: + + case TM_SQDIFF: if (depth == CV_8U) return 300; break; } - CV_Error(cv::Error::StsBadArg, "getTemplateThreshold: unsupported match template mode"); + + CV_Error(Error::StsBadArg, "unsupported match template mode"); return 0; } + /////////////////////////////////////////////////////////////// + // CCORR_32F - void matchTemplate_CCORR_32F( - const GpuMat& image, const GpuMat& templ, GpuMat& result, MatchTemplateBuf &buf, Stream& stream) + class Match_CCORR_32F : public TemplateMatching { - result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); - if (templ.size().area() < getTemplateThreshold(cv::TM_CCORR, CV_32F)) + public: + explicit Match_CCORR_32F(Size user_block_size); + + void match(InputArray image, InputArray templ, OutputArray result, Stream& stream = Stream::Null()); + + private: + Ptr conv_; + GpuMat result_; + }; + + Match_CCORR_32F::Match_CCORR_32F(Size user_block_size) + { + conv_ = gpu::createConvolution(user_block_size); + } + + void Match_CCORR_32F::match(InputArray _image, InputArray _templ, OutputArray _result, Stream& _stream) + { + using namespace cv::gpu::cudev::match_template; + + GpuMat image = _image.getGpuMat(); + GpuMat templ = _templ.getGpuMat(); + + CV_Assert( image.depth() == CV_32F ); + CV_Assert( image.type() == templ.type() ); + CV_Assert( image.cols >= templ.cols && image.rows >= templ.rows ); + + cudaStream_t stream = StreamAccessor::getStream(_stream); + + _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32FC1); + GpuMat result = _result.getGpuMat(); + + if (templ.size().area() < getTemplateThreshold(TM_CCORR, CV_32F)) { - matchTemplateNaive_CCORR_32F(image, templ, result, image.channels(), StreamAccessor::getStream(stream)); + matchTemplateNaive_CCORR_32F(image, templ, result, image.channels(), stream); return; } - Ptr conv = gpu::createConvolution(buf.user_block_size); - if (image.channels() == 1) { - conv->convolve(image.reshape(1), templ.reshape(1), result, true, stream); + conv_->convolve(image.reshape(1), templ.reshape(1), result, true, _stream); } else { - GpuMat result_; - conv->convolve(image.reshape(1), templ.reshape(1), result_, true, stream); - extractFirstChannel_32F(result_, result, image.channels(), StreamAccessor::getStream(stream)); + conv_->convolve(image.reshape(1), templ.reshape(1), result_, true, _stream); + extractFirstChannel_32F(result_, result, image.channels(), stream); } } + /////////////////////////////////////////////////////////////// + // CCORR_8U - void matchTemplate_CCORR_8U( - const GpuMat& image, const GpuMat& templ, GpuMat& result, MatchTemplateBuf &buf, Stream& stream) + class Match_CCORR_8U : public TemplateMatching { - if (templ.size().area() < getTemplateThreshold(cv::TM_CCORR, CV_8U)) + public: + explicit Match_CCORR_8U(Size user_block_size) : match32F_(user_block_size) { - result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); + } + + void match(InputArray image, InputArray templ, OutputArray result, Stream& stream = Stream::Null()); + + private: + GpuMat imagef_, templf_; + Match_CCORR_32F match32F_; + }; + + void Match_CCORR_8U::match(InputArray _image, InputArray _templ, OutputArray _result, Stream& stream) + { + using namespace cv::gpu::cudev::match_template; + + GpuMat image = _image.getGpuMat(); + GpuMat templ = _templ.getGpuMat(); + + CV_Assert( image.depth() == CV_8U ); + CV_Assert( image.type() == templ.type() ); + CV_Assert( image.cols >= templ.cols && image.rows >= templ.rows ); + + if (templ.size().area() < getTemplateThreshold(TM_CCORR, CV_8U)) + { + _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32FC1); + GpuMat result = _result.getGpuMat(); + matchTemplateNaive_CCORR_8U(image, templ, result, image.channels(), StreamAccessor::getStream(stream)); return; } - image.convertTo(buf.imagef, CV_32F, stream); - templ.convertTo(buf.templf, CV_32F, stream); + image.convertTo(imagef_, CV_32F, stream); + templ.convertTo(templf_, CV_32F, stream); - matchTemplate_CCORR_32F(buf.imagef, buf.templf, result, buf, stream); + match32F_.match(imagef_, templf_, _result, stream); } + /////////////////////////////////////////////////////////////// + // CCORR_NORMED_8U - void matchTemplate_CCORR_NORMED_8U( - const GpuMat& image, const GpuMat& templ, GpuMat& result, MatchTemplateBuf &buf, Stream& stream) + class Match_CCORR_NORMED_8U : public TemplateMatching { - matchTemplate_CCORR_8U(image, templ, result, buf, stream); + public: + explicit Match_CCORR_NORMED_8U(Size user_block_size) : match_CCORR_(user_block_size) + { + } - buf.image_sqsums.resize(1); - gpu::sqrIntegral(image.reshape(1), buf.image_sqsums[0], stream); + void match(InputArray image, InputArray templ, OutputArray result, Stream& stream = Stream::Null()); - unsigned long long templ_sqsum = (unsigned long long)gpu::sqrSum(templ.reshape(1))[0]; - normalize_8U(templ.cols, templ.rows, buf.image_sqsums[0], templ_sqsum, result, image.channels(), StreamAccessor::getStream(stream)); + private: + Match_CCORR_8U match_CCORR_; + GpuMat image_sqsums_; + GpuMat intBuffer_; + }; + + void Match_CCORR_NORMED_8U::match(InputArray _image, InputArray _templ, OutputArray _result, Stream& stream) + { + using namespace cv::gpu::cudev::match_template; + + GpuMat image = _image.getGpuMat(); + GpuMat templ = _templ.getGpuMat(); + + CV_Assert( image.depth() == CV_8U ); + CV_Assert( image.type() == templ.type() ); + CV_Assert( image.cols >= templ.cols && image.rows >= templ.rows ); + + match_CCORR_.match(image, templ, _result, stream); + GpuMat result = _result.getGpuMat(); + + gpu::sqrIntegral(image.reshape(1), image_sqsums_, intBuffer_, stream); + + unsigned long long templ_sqsum = (unsigned long long) gpu::sqrSum(templ.reshape(1))[0]; + + normalize_8U(templ.cols, templ.rows, image_sqsums_, templ_sqsum, result, image.channels(), StreamAccessor::getStream(stream)); } + /////////////////////////////////////////////////////////////// + // SQDIFF_32F - void matchTemplate_SQDIFF_32F( - const GpuMat& image, const GpuMat& templ, GpuMat& result, MatchTemplateBuf &buf, Stream& stream) + class Match_SQDIFF_32F : public TemplateMatching { - (void)buf; - result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); + public: + void match(InputArray image, InputArray templ, OutputArray result, Stream& stream = Stream::Null()); + }; + + void Match_SQDIFF_32F::match(InputArray _image, InputArray _templ, OutputArray _result, Stream& stream) + { + using namespace cv::gpu::cudev::match_template; + + GpuMat image = _image.getGpuMat(); + GpuMat templ = _templ.getGpuMat(); + + CV_Assert( image.depth() == CV_32F ); + CV_Assert( image.type() == templ.type() ); + CV_Assert( image.cols >= templ.cols && image.rows >= templ.rows ); + + _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32FC1); + GpuMat result = _result.getGpuMat(); + matchTemplateNaive_SQDIFF_32F(image, templ, result, image.channels(), StreamAccessor::getStream(stream)); } + /////////////////////////////////////////////////////////////// + // SQDIFF_8U - void matchTemplate_SQDIFF_8U( - const GpuMat& image, const GpuMat& templ, GpuMat& result, MatchTemplateBuf &buf, Stream& stream) + class Match_SQDIFF_8U : public TemplateMatching { - if (templ.size().area() < getTemplateThreshold(cv::TM_SQDIFF, CV_8U)) + public: + explicit Match_SQDIFF_8U(Size user_block_size) : match_CCORR_(user_block_size) { - result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32F); + } + + void match(InputArray image, InputArray templ, OutputArray result, Stream& stream = Stream::Null()); + + private: + GpuMat image_sqsums_; + GpuMat intBuffer_; + Match_CCORR_8U match_CCORR_; + }; + + void Match_SQDIFF_8U::match(InputArray _image, InputArray _templ, OutputArray _result, Stream& stream) + { + using namespace cv::gpu::cudev::match_template; + + GpuMat image = _image.getGpuMat(); + GpuMat templ = _templ.getGpuMat(); + + CV_Assert( image.depth() == CV_8U ); + CV_Assert( image.type() == templ.type() ); + CV_Assert( image.cols >= templ.cols && image.rows >= templ.rows ); + + if (templ.size().area() < getTemplateThreshold(TM_SQDIFF, CV_8U)) + { + _result.create(image.rows - templ.rows + 1, image.cols - templ.cols + 1, CV_32FC1); + GpuMat result = _result.getGpuMat(); + matchTemplateNaive_SQDIFF_8U(image, templ, result, image.channels(), StreamAccessor::getStream(stream)); return; } - buf.image_sqsums.resize(1); - gpu::sqrIntegral(image.reshape(1), buf.image_sqsums[0], stream); + gpu::sqrIntegral(image.reshape(1), image_sqsums_, intBuffer_, stream); - unsigned long long templ_sqsum = (unsigned long long)gpu::sqrSum(templ.reshape(1))[0]; + unsigned long long templ_sqsum = (unsigned long long) gpu::sqrSum(templ.reshape(1))[0]; - matchTemplate_CCORR_8U(image, templ, result, buf, stream); - matchTemplatePrepared_SQDIFF_8U(templ.cols, templ.rows, buf.image_sqsums[0], templ_sqsum, result, image.channels(), StreamAccessor::getStream(stream)); + match_CCORR_.match(image, templ, _result, stream); + GpuMat result = _result.getGpuMat(); + + matchTemplatePrepared_SQDIFF_8U(templ.cols, templ.rows, image_sqsums_, templ_sqsum, result, image.channels(), StreamAccessor::getStream(stream)); } + /////////////////////////////////////////////////////////////// + // SQDIFF_NORMED_8U - void matchTemplate_SQDIFF_NORMED_8U( - const GpuMat& image, const GpuMat& templ, GpuMat& result, MatchTemplateBuf &buf, Stream& stream) + class Match_SQDIFF_NORMED_8U : public TemplateMatching { - buf.image_sqsums.resize(1); - gpu::sqrIntegral(image.reshape(1), buf.image_sqsums[0], stream); + public: + explicit Match_SQDIFF_NORMED_8U(Size user_block_size) : match_CCORR_(user_block_size) + { + } - unsigned long long templ_sqsum = (unsigned long long)gpu::sqrSum(templ.reshape(1))[0]; + void match(InputArray image, InputArray templ, OutputArray result, Stream& stream = Stream::Null()); - matchTemplate_CCORR_8U(image, templ, result, buf, stream); - matchTemplatePrepared_SQDIFF_NORMED_8U(templ.cols, templ.rows, buf.image_sqsums[0], templ_sqsum, result, image.channels(), StreamAccessor::getStream(stream)); + private: + GpuMat image_sqsums_; + GpuMat intBuffer_; + Match_CCORR_8U match_CCORR_; + }; + + void Match_SQDIFF_NORMED_8U::match(InputArray _image, InputArray _templ, OutputArray _result, Stream& stream) + { + using namespace cv::gpu::cudev::match_template; + + GpuMat image = _image.getGpuMat(); + GpuMat templ = _templ.getGpuMat(); + + CV_Assert( image.depth() == CV_8U ); + CV_Assert( image.type() == templ.type() ); + CV_Assert( image.cols >= templ.cols && image.rows >= templ.rows ); + + gpu::sqrIntegral(image.reshape(1), image_sqsums_, intBuffer_, stream); + + unsigned long long templ_sqsum = (unsigned long long) gpu::sqrSum(templ.reshape(1))[0]; + + match_CCORR_.match(image, templ, _result, stream); + GpuMat result = _result.getGpuMat(); + + matchTemplatePrepared_SQDIFF_NORMED_8U(templ.cols, templ.rows, image_sqsums_, templ_sqsum, result, image.channels(), StreamAccessor::getStream(stream)); } + /////////////////////////////////////////////////////////////// + // CCOFF_8U - void matchTemplate_CCOFF_8U( - const GpuMat& image, const GpuMat& templ, GpuMat& result, MatchTemplateBuf &buf, Stream& stream) + class Match_CCOEFF_8U : public TemplateMatching { - matchTemplate_CCORR_8U(image, templ, result, buf, stream); + public: + explicit Match_CCOEFF_8U(Size user_block_size) : match_CCORR_(user_block_size) + { + } + + void match(InputArray image, InputArray templ, OutputArray result, Stream& stream = Stream::Null()); + + private: + GpuMat intBuffer_; + std::vector images_; + std::vector image_sums_; + Match_CCORR_8U match_CCORR_; + }; + + void Match_CCOEFF_8U::match(InputArray _image, InputArray _templ, OutputArray _result, Stream& stream) + { + using namespace cv::gpu::cudev::match_template; + + GpuMat image = _image.getGpuMat(); + GpuMat templ = _templ.getGpuMat(); + + CV_Assert( image.depth() == CV_8U ); + CV_Assert( image.type() == templ.type() ); + CV_Assert( image.cols >= templ.cols && image.rows >= templ.rows ); + + match_CCORR_.match(image, templ, _result, stream); + GpuMat result = _result.getGpuMat(); if (image.channels() == 1) { - buf.image_sums.resize(1); - gpu::integral(image, buf.image_sums[0], stream); + image_sums_.resize(1); + gpu::integral(image, image_sums_[0], intBuffer_, stream); - unsigned int templ_sum = (unsigned int)gpu::sum(templ)[0]; - matchTemplatePrepared_CCOFF_8U(templ.cols, templ.rows, buf.image_sums[0], templ_sum, result, StreamAccessor::getStream(stream)); + unsigned int templ_sum = (unsigned int) gpu::sum(templ)[0]; + + matchTemplatePrepared_CCOFF_8U(templ.cols, templ.rows, image_sums_[0], templ_sum, result, StreamAccessor::getStream(stream)); } else { - gpu::split(image, buf.images); - buf.image_sums.resize(buf.images.size()); + gpu::split(image, images_); + + image_sums_.resize(images_.size()); for (int i = 0; i < image.channels(); ++i) - gpu::integral(buf.images[i], buf.image_sums[i], stream); + gpu::integral(images_[i], image_sums_[i], intBuffer_, stream); Scalar templ_sum = gpu::sum(templ); @@ -285,60 +464,91 @@ namespace { case 2: matchTemplatePrepared_CCOFF_8UC2( - templ.cols, templ.rows, buf.image_sums[0], buf.image_sums[1], - (unsigned int)templ_sum[0], (unsigned int)templ_sum[1], + templ.cols, templ.rows, image_sums_[0], image_sums_[1], + (unsigned int) templ_sum[0], (unsigned int) templ_sum[1], result, StreamAccessor::getStream(stream)); break; case 3: matchTemplatePrepared_CCOFF_8UC3( - templ.cols, templ.rows, buf.image_sums[0], buf.image_sums[1], buf.image_sums[2], - (unsigned int)templ_sum[0], (unsigned int)templ_sum[1], (unsigned int)templ_sum[2], + templ.cols, templ.rows, image_sums_[0], image_sums_[1], image_sums_[2], + (unsigned int) templ_sum[0], (unsigned int) templ_sum[1], (unsigned int) templ_sum[2], result, StreamAccessor::getStream(stream)); break; case 4: matchTemplatePrepared_CCOFF_8UC4( - templ.cols, templ.rows, buf.image_sums[0], buf.image_sums[1], buf.image_sums[2], buf.image_sums[3], - (unsigned int)templ_sum[0], (unsigned int)templ_sum[1], (unsigned int)templ_sum[2], - (unsigned int)templ_sum[3], result, StreamAccessor::getStream(stream)); + templ.cols, templ.rows, image_sums_[0], image_sums_[1], image_sums_[2], image_sums_[3], + (unsigned int) templ_sum[0], (unsigned int) templ_sum[1], (unsigned int) templ_sum[2], (unsigned int) templ_sum[3], + result, StreamAccessor::getStream(stream)); break; default: - CV_Error(cv::Error::StsBadArg, "matchTemplate: unsupported number of channels"); + CV_Error(Error::StsBadArg, "unsupported number of channels"); } } } + /////////////////////////////////////////////////////////////// + // CCOFF_NORMED_8U - void matchTemplate_CCOFF_NORMED_8U( - const GpuMat& image, const GpuMat& templ, GpuMat& result, MatchTemplateBuf &buf, Stream& stream) + class Match_CCOEFF_NORMED_8U : public TemplateMatching { - image.convertTo(buf.imagef, CV_32F, stream); - templ.convertTo(buf.templf, CV_32F, stream); + public: + explicit Match_CCOEFF_NORMED_8U(Size user_block_size) : match_CCORR_32F_(user_block_size) + { + } - matchTemplate_CCORR_32F(buf.imagef, buf.templf, result, buf, stream); + void match(InputArray image, InputArray templ, OutputArray result, Stream& stream = Stream::Null()); + + private: + GpuMat imagef_, templf_; + Match_CCORR_32F match_CCORR_32F_; + GpuMat intBuffer_; + std::vector images_; + std::vector image_sums_; + std::vector image_sqsums_; + }; + + void Match_CCOEFF_NORMED_8U::match(InputArray _image, InputArray _templ, OutputArray _result, Stream& stream) + { + using namespace cv::gpu::cudev::match_template; + + GpuMat image = _image.getGpuMat(); + GpuMat templ = _templ.getGpuMat(); + + CV_Assert( image.depth() == CV_8U ); + CV_Assert( image.type() == templ.type() ); + CV_Assert( image.cols >= templ.cols && image.rows >= templ.rows ); + + image.convertTo(imagef_, CV_32F, stream); + templ.convertTo(templf_, CV_32F, stream); + + match_CCORR_32F_.match(imagef_, templf_, _result, stream); + GpuMat result = _result.getGpuMat(); if (image.channels() == 1) { - buf.image_sums.resize(1); - gpu::integral(image, buf.image_sums[0], stream); - buf.image_sqsums.resize(1); - gpu::sqrIntegral(image, buf.image_sqsums[0], stream); + image_sums_.resize(1); + gpu::integral(image, image_sums_[0], intBuffer_, stream); - unsigned int templ_sum = (unsigned int)gpu::sum(templ)[0]; - unsigned long long templ_sqsum = (unsigned long long)gpu::sqrSum(templ)[0]; + image_sqsums_.resize(1); + gpu::sqrIntegral(image, image_sqsums_[0], intBuffer_, stream); + + unsigned int templ_sum = (unsigned int) gpu::sum(templ)[0]; + unsigned long long templ_sqsum = (unsigned long long) gpu::sqrSum(templ)[0]; matchTemplatePrepared_CCOFF_NORMED_8U( - templ.cols, templ.rows, buf.image_sums[0], buf.image_sqsums[0], + templ.cols, templ.rows, image_sums_[0], image_sqsums_[0], templ_sum, templ_sqsum, result, StreamAccessor::getStream(stream)); } else { - gpu::split(image, buf.images); - buf.image_sums.resize(buf.images.size()); - buf.image_sqsums.resize(buf.images.size()); + gpu::split(image, images_); + + image_sums_.resize(images_.size()); + image_sqsums_.resize(images_.size()); for (int i = 0; i < image.channels(); ++i) { - gpu::integral(buf.images[i], buf.image_sums[i], stream); - gpu::sqrIntegral(buf.images[i], buf.image_sqsums[i], stream); + gpu::integral(images_[i], image_sums_[i], intBuffer_, stream); + gpu::sqrIntegral(images_[i], image_sqsums_[i], intBuffer_, stream); } Scalar templ_sum = gpu::sum(templ); @@ -349,8 +559,8 @@ namespace case 2: matchTemplatePrepared_CCOFF_NORMED_8UC2( templ.cols, templ.rows, - buf.image_sums[0], buf.image_sqsums[0], - buf.image_sums[1], buf.image_sqsums[1], + image_sums_[0], image_sqsums_[0], + image_sums_[1], image_sqsums_[1], (unsigned int)templ_sum[0], (unsigned long long)templ_sqsum[0], (unsigned int)templ_sum[1], (unsigned long long)templ_sqsum[1], result, StreamAccessor::getStream(stream)); @@ -358,9 +568,9 @@ namespace case 3: matchTemplatePrepared_CCOFF_NORMED_8UC3( templ.cols, templ.rows, - buf.image_sums[0], buf.image_sqsums[0], - buf.image_sums[1], buf.image_sqsums[1], - buf.image_sums[2], buf.image_sqsums[2], + image_sums_[0], image_sqsums_[0], + image_sums_[1], image_sqsums_[1], + image_sums_[2], image_sqsums_[2], (unsigned int)templ_sum[0], (unsigned long long)templ_sqsum[0], (unsigned int)templ_sum[1], (unsigned long long)templ_sqsum[1], (unsigned int)templ_sum[2], (unsigned long long)templ_sqsum[2], @@ -369,10 +579,10 @@ namespace case 4: matchTemplatePrepared_CCOFF_NORMED_8UC4( templ.cols, templ.rows, - buf.image_sums[0], buf.image_sqsums[0], - buf.image_sums[1], buf.image_sqsums[1], - buf.image_sums[2], buf.image_sqsums[2], - buf.image_sums[3], buf.image_sqsums[3], + image_sums_[0], image_sqsums_[0], + image_sums_[1], image_sqsums_[1], + image_sums_[2], image_sqsums_[2], + image_sums_[3], image_sqsums_[3], (unsigned int)templ_sum[0], (unsigned long long)templ_sqsum[0], (unsigned int)templ_sum[1], (unsigned long long)templ_sqsum[1], (unsigned int)templ_sum[2], (unsigned long long)templ_sqsum[2], @@ -380,46 +590,60 @@ namespace result, StreamAccessor::getStream(stream)); break; default: - CV_Error(cv::Error::StsBadArg, "matchTemplate: unsupported number of channels"); + CV_Error(Error::StsBadArg, "unsupported number of channels"); } } } } - -void cv::gpu::matchTemplate(const GpuMat& image, const GpuMat& templ, GpuMat& result, int method, Stream& stream) +Ptr cv::gpu::createTemplateMatching(int srcType, int method, Size user_block_size) { - MatchTemplateBuf buf; - matchTemplate(image, templ, result, method, buf, stream); -} + const int sdepth = CV_MAT_DEPTH(srcType); + CV_Assert( sdepth == CV_8U || sdepth == CV_32F ); -void cv::gpu::matchTemplate( - const GpuMat& image, const GpuMat& templ, GpuMat& result, int method, - MatchTemplateBuf &buf, Stream& stream) -{ - CV_Assert(image.type() == templ.type()); - CV_Assert(image.cols >= templ.cols && image.rows >= templ.rows); - - typedef void (*Caller)(const GpuMat&, const GpuMat&, GpuMat&, MatchTemplateBuf&, Stream& stream); - - static const Caller callers8U[] = { ::matchTemplate_SQDIFF_8U, ::matchTemplate_SQDIFF_NORMED_8U, - ::matchTemplate_CCORR_8U, ::matchTemplate_CCORR_NORMED_8U, - ::matchTemplate_CCOFF_8U, ::matchTemplate_CCOFF_NORMED_8U }; - static const Caller callers32F[] = { ::matchTemplate_SQDIFF_32F, 0, - ::matchTemplate_CCORR_32F, 0, 0, 0 }; - - const Caller* callers = 0; - switch (image.depth()) + if (sdepth == CV_32F) { - case CV_8U: callers = callers8U; break; - case CV_32F: callers = callers32F; break; - default: CV_Error(cv::Error::StsBadArg, "matchTemplate: unsupported data type"); - } + switch (method) + { + case TM_SQDIFF: + return makePtr(); - Caller caller = callers[method]; - CV_Assert(caller); - caller(image, templ, result, buf, stream); + case TM_CCORR: + return makePtr(user_block_size); + + default: + CV_Error( Error::StsBadFlag, "Unsopported method" ); + return Ptr(); + } + } + else + { + switch (method) + { + case TM_SQDIFF: + return makePtr(user_block_size); + + case TM_SQDIFF_NORMED: + return makePtr(user_block_size); + + case TM_CCORR: + return makePtr(user_block_size); + + case TM_CCORR_NORMED: + return makePtr(user_block_size); + + case TM_CCOEFF: + return makePtr(user_block_size); + + case TM_CCOEFF_NORMED: + return makePtr(user_block_size); + + default: + CV_Error( Error::StsBadFlag, "Unsopported method" ); + return Ptr(); + } + } } #endif diff --git a/modules/gpuimgproc/src/mean_shift.cpp b/modules/gpuimgproc/src/mean_shift.cpp index e30f95bf9..26368ca5a 100644 --- a/modules/gpuimgproc/src/mean_shift.cpp +++ b/modules/gpuimgproc/src/mean_shift.cpp @@ -47,13 +47,13 @@ using namespace cv::gpu; #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) -void cv::gpu::meanShiftFiltering(const GpuMat&, GpuMat&, int, int, TermCriteria, Stream&) { throw_no_cuda(); } -void cv::gpu::meanShiftProc(const GpuMat&, GpuMat&, GpuMat&, int, int, TermCriteria, Stream&) { throw_no_cuda(); } +void cv::gpu::meanShiftFiltering(InputArray, OutputArray, int, int, TermCriteria, Stream&) { throw_no_cuda(); } +void cv::gpu::meanShiftProc(InputArray, OutputArray, OutputArray, int, int, TermCriteria, Stream&) { throw_no_cuda(); } #else /* !defined (HAVE_CUDA) */ //////////////////////////////////////////////////////////////////////// -// meanShiftFiltering_GPU +// meanShiftFiltering namespace cv { namespace gpu { namespace cudev { @@ -63,27 +63,26 @@ namespace cv { namespace gpu { namespace cudev } }}} -void cv::gpu::meanShiftFiltering(const GpuMat& src, GpuMat& dst, int sp, int sr, TermCriteria criteria, Stream& stream) +void cv::gpu::meanShiftFiltering(InputArray _src, OutputArray _dst, int sp, int sr, TermCriteria criteria, Stream& stream) { using namespace ::cv::gpu::cudev::imgproc; - if( src.empty() ) - CV_Error( cv::Error::StsBadArg, "The input image is empty" ); + GpuMat src = _src.getGpuMat(); - if( src.depth() != CV_8U || src.channels() != 4 ) - CV_Error( cv::Error::StsUnsupportedFormat, "Only 8-bit, 4-channel images are supported" ); + CV_Assert( src.type() == CV_8UC4 ); - dst.create( src.size(), CV_8UC4 ); + _dst.create(src.size(), CV_8UC4); + GpuMat dst = _dst.getGpuMat(); - if( !(criteria.type & TermCriteria::MAX_ITER) ) + if (!(criteria.type & TermCriteria::MAX_ITER)) criteria.maxCount = 5; int maxIter = std::min(std::max(criteria.maxCount, 1), 100); - float eps; - if( !(criteria.type & TermCriteria::EPS) ) - eps = 1.f; - eps = (float)std::max(criteria.epsilon, 0.0); + if (!(criteria.type & TermCriteria::EPS)) + criteria.epsilon = 1.f; + + float eps = (float) std::max(criteria.epsilon, 0.0); meanShiftFiltering_gpu(src, dst, sp, sr, maxIter, eps, StreamAccessor::getStream(stream)); } @@ -99,28 +98,29 @@ namespace cv { namespace gpu { namespace cudev } }}} -void cv::gpu::meanShiftProc(const GpuMat& src, GpuMat& dstr, GpuMat& dstsp, int sp, int sr, TermCriteria criteria, Stream& stream) +void cv::gpu::meanShiftProc(InputArray _src, OutputArray _dstr, OutputArray _dstsp, int sp, int sr, TermCriteria criteria, Stream& stream) { using namespace ::cv::gpu::cudev::imgproc; - if( src.empty() ) - CV_Error( cv::Error::StsBadArg, "The input image is empty" ); + GpuMat src = _src.getGpuMat(); - if( src.depth() != CV_8U || src.channels() != 4 ) - CV_Error( cv::Error::StsUnsupportedFormat, "Only 8-bit, 4-channel images are supported" ); + CV_Assert( src.type() == CV_8UC4 ); - dstr.create( src.size(), CV_8UC4 ); - dstsp.create( src.size(), CV_16SC2 ); + _dstr.create(src.size(), CV_8UC4); + _dstsp.create(src.size(), CV_16SC2); - if( !(criteria.type & TermCriteria::MAX_ITER) ) + GpuMat dstr = _dstr.getGpuMat(); + GpuMat dstsp = _dstsp.getGpuMat(); + + if (!(criteria.type & TermCriteria::MAX_ITER)) criteria.maxCount = 5; int maxIter = std::min(std::max(criteria.maxCount, 1), 100); - float eps; - if( !(criteria.type & TermCriteria::EPS) ) - eps = 1.f; - eps = (float)std::max(criteria.epsilon, 0.0); + if (!(criteria.type & TermCriteria::EPS)) + criteria.epsilon = 1.f; + + float eps = (float) std::max(criteria.epsilon, 0.0); meanShiftProc_gpu(src, dstr, dstsp, sp, sr, maxIter, eps, StreamAccessor::getStream(stream)); } diff --git a/modules/gpuimgproc/src/mssegmentation.cpp b/modules/gpuimgproc/src/mssegmentation.cpp index 7f02168e1..ec1c5feb4 100644 --- a/modules/gpuimgproc/src/mssegmentation.cpp +++ b/modules/gpuimgproc/src/mssegmentation.cpp @@ -43,7 +43,7 @@ #if !defined HAVE_CUDA || defined(CUDA_DISABLER) -void cv::gpu::meanShiftSegmentation(const GpuMat&, Mat&, int, int, int, TermCriteria) { throw_no_cuda(); } +void cv::gpu::meanShiftSegmentation(InputArray, OutputArray, int, int, int, TermCriteria) { throw_no_cuda(); } #else @@ -222,9 +222,12 @@ inline int dist2(const cv::Vec2s& lhs, const cv::Vec2s& rhs) } // anonymous namespace -void cv::gpu::meanShiftSegmentation(const GpuMat& src, Mat& dst, int sp, int sr, int minsize, TermCriteria criteria) +void cv::gpu::meanShiftSegmentation(InputArray _src, OutputArray _dst, int sp, int sr, int minsize, TermCriteria criteria) { - CV_Assert(src.type() == CV_8UC4); + GpuMat src = _src.getGpuMat(); + + CV_Assert( src.type() == CV_8UC4 ); + const int nrows = src.rows; const int ncols = src.cols; const int hr = sr; @@ -232,7 +235,7 @@ void cv::gpu::meanShiftSegmentation(const GpuMat& src, Mat& dst, int sp, int sr, // Perform mean shift procedure and obtain region and spatial maps GpuMat d_rmap, d_spmap; - meanShiftProc(src, d_rmap, d_spmap, sp, sr, criteria); + gpu::meanShiftProc(src, d_rmap, d_spmap, sp, sr, criteria); Mat rmap(d_rmap); Mat spmap(d_spmap); @@ -337,7 +340,7 @@ void cv::gpu::meanShiftSegmentation(const GpuMat& src, Mat& dst, int sp, int sr, } // Sort all graph's edges connecting differnet components (in asceding order) - sort(edges.begin(), edges.end()); + std::sort(edges.begin(), edges.end()); // Exclude small components (starting from the nearest couple) for (size_t i = 0; i < edges.size(); ++i) @@ -366,7 +369,8 @@ void cv::gpu::meanShiftSegmentation(const GpuMat& src, Mat& dst, int sp, int sr, } // Create final image, color of each segment is the average color of its pixels - dst.create(src.size(), src.type()); + _dst.create(src.size(), src.type()); + Mat dst = _dst.getMat(); for (int y = 0; y < nrows; ++y) { diff --git a/modules/gpuimgproc/src/precomp.cpp b/modules/gpuimgproc/src/precomp.cpp deleted file mode 100644 index 3c01a2596..000000000 --- a/modules/gpuimgproc/src/precomp.cpp +++ /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 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" diff --git a/modules/gpuimgproc/src/precomp.hpp b/modules/gpuimgproc/src/precomp.hpp index 1417c874b..b1edbf123 100644 --- a/modules/gpuimgproc/src/precomp.hpp +++ b/modules/gpuimgproc/src/precomp.hpp @@ -44,8 +44,8 @@ #define __OPENCV_PRECOMP_H__ #include "opencv2/gpuimgproc.hpp" -#include "opencv2/gpufilters.hpp" +#include "opencv2/core/utility.hpp" #include "opencv2/core/private.hpp" #include "opencv2/core/private.gpu.hpp" @@ -55,4 +55,8 @@ # include "opencv2/gpuarithm.hpp" #endif +#ifdef HAVE_OPENCV_GPUFILTERS +# include "opencv2/gpufilters.hpp" +#endif + #endif /* __OPENCV_PRECOMP_H__ */ diff --git a/modules/gpuimgproc/test/test_canny.cpp b/modules/gpuimgproc/test/test_canny.cpp index b3ab5addc..3d9d35016 100644 --- a/modules/gpuimgproc/test/test_canny.cpp +++ b/modules/gpuimgproc/test/test_canny.cpp @@ -81,28 +81,15 @@ GPU_TEST_P(Canny, Accuracy) double low_thresh = 50.0; double high_thresh = 100.0; - if (!supportFeature(devInfo, cv::gpu::SHARED_ATOMICS)) - { - try - { - cv::gpu::GpuMat edges; - cv::gpu::Canny(loadMat(img), edges, low_thresh, high_thresh, apperture_size, useL2gradient); - } - catch (const cv::Exception& e) - { - ASSERT_EQ(cv::Error::StsNotImplemented, e.code); - } - } - else - { - cv::gpu::GpuMat edges; - cv::gpu::Canny(loadMat(img, useRoi), edges, low_thresh, high_thresh, apperture_size, useL2gradient); + cv::Ptr canny = cv::gpu::createCannyEdgeDetector(low_thresh, high_thresh, apperture_size, useL2gradient); - cv::Mat edges_gold; - cv::Canny(img, edges_gold, low_thresh, high_thresh, apperture_size, useL2gradient); + cv::gpu::GpuMat edges; + canny->detect(loadMat(img, useRoi), edges); - EXPECT_MAT_SIMILAR(edges_gold, edges, 2e-2); - } + cv::Mat edges_gold; + cv::Canny(img, edges_gold, low_thresh, high_thresh, apperture_size, useL2gradient); + + EXPECT_MAT_SIMILAR(edges_gold, edges, 2e-2); } INSTANTIATE_TEST_CASE_P(GPU_ImgProc, Canny, testing::Combine( diff --git a/modules/gpuimgproc/test/test_corners.cpp b/modules/gpuimgproc/test/test_corners.cpp index 54d8df457..262548056 100644 --- a/modules/gpuimgproc/test/test_corners.cpp +++ b/modules/gpuimgproc/test/test_corners.cpp @@ -82,8 +82,10 @@ GPU_TEST_P(CornerHarris, Accuracy) double k = randomDouble(0.1, 0.9); + cv::Ptr harris = cv::gpu::createHarrisCorner(src.type(), blockSize, apertureSize, k, borderType); + cv::gpu::GpuMat dst; - cv::gpu::cornerHarris(loadMat(src), dst, blockSize, apertureSize, k, borderType); + harris->compute(loadMat(src), dst); cv::Mat dst_gold; cv::cornerHarris(src, dst_gold, blockSize, apertureSize, k, borderType); @@ -126,8 +128,10 @@ GPU_TEST_P(CornerMinEigen, Accuracy) cv::Mat src = readImageType("stereobm/aloe-L.png", type); ASSERT_FALSE(src.empty()); + cv::Ptr minEigenVal = cv::gpu::createMinEigenValCorner(src.type(), blockSize, apertureSize, borderType); + cv::gpu::GpuMat dst; - cv::gpu::cornerMinEigenVal(loadMat(src), dst, blockSize, apertureSize, borderType); + minEigenVal->compute(loadMat(src), dst); cv::Mat dst_gold; cv::cornerMinEigenVal(src, dst_gold, blockSize, apertureSize, borderType); diff --git a/modules/gpuimgproc/test/test_gftt.cpp b/modules/gpuimgproc/test/test_gftt.cpp index b20df33ae..6ba6e0cff 100644 --- a/modules/gpuimgproc/test/test_gftt.cpp +++ b/modules/gpuimgproc/test/test_gftt.cpp @@ -76,10 +76,10 @@ GPU_TEST_P(GoodFeaturesToTrack, Accuracy) int maxCorners = 1000; double qualityLevel = 0.01; - cv::gpu::GoodFeaturesToTrackDetector_GPU detector(maxCorners, qualityLevel, minDistance); + cv::Ptr detector = cv::gpu::createGoodFeaturesToTrackDetector(image.type(), maxCorners, qualityLevel, minDistance); cv::gpu::GpuMat d_pts; - detector(loadMat(image), d_pts); + detector->detect(loadMat(image), d_pts); ASSERT_FALSE(d_pts.empty()); @@ -114,12 +114,12 @@ GPU_TEST_P(GoodFeaturesToTrack, EmptyCorners) int maxCorners = 1000; double qualityLevel = 0.01; - cv::gpu::GoodFeaturesToTrackDetector_GPU detector(maxCorners, qualityLevel, minDistance); - cv::gpu::GpuMat src(100, 100, CV_8UC1, cv::Scalar::all(0)); cv::gpu::GpuMat corners(1, maxCorners, CV_32FC2); - detector(src, corners); + cv::Ptr detector = cv::gpu::createGoodFeaturesToTrackDetector(src.type(), maxCorners, qualityLevel, minDistance); + + detector->detect(src, corners); ASSERT_TRUE(corners.empty()); } diff --git a/modules/gpuimgproc/test/test_histogram.cpp b/modules/gpuimgproc/test/test_histogram.cpp index c3d17d2a1..556211729 100644 --- a/modules/gpuimgproc/test/test_histogram.cpp +++ b/modules/gpuimgproc/test/test_histogram.cpp @@ -49,13 +49,16 @@ using namespace cvtest; /////////////////////////////////////////////////////////////////////////////////////////////////////// // HistEven -struct HistEven : testing::TestWithParam +PARAM_TEST_CASE(HistEven, cv::gpu::DeviceInfo, cv::Size) { cv::gpu::DeviceInfo devInfo; + cv::Size size; + virtual void SetUp() { - devInfo = GetParam(); + devInfo = GET_PARAM(0); + size = GET_PARAM(1); cv::gpu::setDevice(devInfo.deviceID()); } @@ -63,57 +66,34 @@ struct HistEven : testing::TestWithParam GPU_TEST_P(HistEven, Accuracy) { - cv::Mat img = readImage("stereobm/aloe-L.png"); - ASSERT_FALSE(img.empty()); - - cv::Mat hsv; - cv::cvtColor(img, hsv, cv::COLOR_BGR2HSV); + cv::Mat src = randomMat(size, CV_8UC1); int hbins = 30; - float hranges[] = {0.0f, 180.0f}; - - std::vector srcs; - cv::gpu::split(loadMat(hsv), srcs); + float hranges[] = {50.0f, 200.0f}; cv::gpu::GpuMat hist; - cv::gpu::histEven(srcs[0], hist, hbins, (int)hranges[0], (int)hranges[1]); + cv::gpu::histEven(loadMat(src), hist, hbins, (int) hranges[0], (int) hranges[1]); + + cv::Mat hist_gold; - cv::MatND histnd; int histSize[] = {hbins}; const float* ranges[] = {hranges}; int channels[] = {0}; - cv::calcHist(&hsv, 1, channels, cv::Mat(), histnd, 1, histSize, ranges); + cv::calcHist(&src, 1, channels, cv::Mat(), hist_gold, 1, histSize, ranges); - cv::Mat hist_gold = histnd; hist_gold = hist_gold.t(); hist_gold.convertTo(hist_gold, CV_32S); EXPECT_MAT_NEAR(hist_gold, hist, 0.0); } -INSTANTIATE_TEST_CASE_P(GPU_ImgProc, HistEven, ALL_DEVICES); +INSTANTIATE_TEST_CASE_P(GPU_ImgProc, HistEven, testing::Combine( + ALL_DEVICES, + DIFFERENT_SIZES)); /////////////////////////////////////////////////////////////////////////////////////////////////////// // CalcHist -namespace -{ - 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]]; - } - } -} - PARAM_TEST_CASE(CalcHist, cv::gpu::DeviceInfo, cv::Size) { cv::gpu::DeviceInfo devInfo; @@ -137,7 +117,16 @@ GPU_TEST_P(CalcHist, Accuracy) cv::gpu::calcHist(loadMat(src), hist); cv::Mat hist_gold; - calcHistGold(src, hist_gold); + + const int hbins = 256; + const float hranges[] = {0.0f, 256.0f}; + const int histSize[] = {hbins}; + const float* ranges[] = {hranges}; + const int channels[] = {0}; + + cv::calcHist(&src, 1, channels, cv::Mat(), hist_gold, 1, histSize, ranges); + hist_gold = hist_gold.reshape(1, 1); + hist_gold.convertTo(hist_gold, CV_32S); EXPECT_MAT_NEAR(hist_gold, hist, 0.0); } diff --git a/modules/gpuimgproc/test/test_hough.cpp b/modules/gpuimgproc/test/test_hough.cpp index a04490104..969899d8b 100644 --- a/modules/gpuimgproc/test/test_hough.cpp +++ b/modules/gpuimgproc/test/test_hough.cpp @@ -94,11 +94,13 @@ GPU_TEST_P(HoughLines, Accuracy) cv::Mat src(size, CV_8UC1); generateLines(src); + cv::Ptr hough = cv::gpu::createHoughLinesDetector(rho, theta, threshold); + cv::gpu::GpuMat d_lines; - cv::gpu::HoughLines(loadMat(src, useRoi), d_lines, rho, theta, threshold); + hough->detect(loadMat(src, useRoi), d_lines); std::vector lines; - cv::gpu::HoughLinesDownload(d_lines, lines); + hough->downloadResults(d_lines, lines); cv::Mat dst(size, CV_8UC1); drawLines(dst, lines); @@ -148,11 +150,13 @@ GPU_TEST_P(HoughCircles, Accuracy) cv::Mat src(size, CV_8UC1); drawCircles(src, circles_gold, true); + cv::Ptr houghCircles = cv::gpu::createHoughCirclesDetector(dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius); + cv::gpu::GpuMat d_circles; - cv::gpu::HoughCircles(loadMat(src, useRoi), d_circles, cv::HOUGH_GRADIENT, dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius); + houghCircles->detect(loadMat(src, useRoi), d_circles); std::vector circles; - cv::gpu::HoughCirclesDownload(d_circles, circles); + d_circles.download(circles); ASSERT_FALSE(circles.empty()); @@ -189,7 +193,7 @@ PARAM_TEST_CASE(GeneralizedHough, cv::gpu::DeviceInfo, UseRoi) { }; -GPU_TEST_P(GeneralizedHough, POSITION) +GPU_TEST_P(GeneralizedHough, Ballard) { const cv::gpu::DeviceInfo devInfo = GET_PARAM(0); cv::gpu::setDevice(devInfo.deviceID()); @@ -214,16 +218,16 @@ GPU_TEST_P(GeneralizedHough, POSITION) templ.copyTo(imageROI); } - cv::Ptr hough = cv::gpu::GeneralizedHough_GPU::create(cv::GeneralizedHough::GHT_POSITION); - hough->set("votesThreshold", 200); + cv::Ptr alg = cv::gpu::createGeneralizedHoughBallard(); + alg->setVotesThreshold(200); - hough->setTemplate(loadMat(templ, useRoi)); + alg->setTemplate(loadMat(templ, useRoi)); cv::gpu::GpuMat d_pos; - hough->detect(loadMat(image, useRoi), d_pos); + alg->detect(loadMat(image, useRoi), d_pos); std::vector pos; - hough->download(d_pos, pos); + d_pos.download(pos); ASSERT_EQ(gold_count, pos.size()); diff --git a/modules/gpuimgproc/test/test_match_template.cpp b/modules/gpuimgproc/test/test_match_template.cpp index d18757923..b6fd16140 100644 --- a/modules/gpuimgproc/test/test_match_template.cpp +++ b/modules/gpuimgproc/test/test_match_template.cpp @@ -82,8 +82,10 @@ GPU_TEST_P(MatchTemplate8U, Accuracy) cv::Mat image = randomMat(size, CV_MAKETYPE(CV_8U, cn)); cv::Mat templ = randomMat(templ_size, CV_MAKETYPE(CV_8U, cn)); + cv::Ptr alg = cv::gpu::createTemplateMatching(image.type(), method); + cv::gpu::GpuMat dst; - cv::gpu::matchTemplate(loadMat(image), loadMat(templ), dst, method); + alg->match(loadMat(image), loadMat(templ), dst); cv::Mat dst_gold; cv::matchTemplate(image, templ, dst_gold, method); @@ -128,8 +130,10 @@ GPU_TEST_P(MatchTemplate32F, Regression) cv::Mat image = randomMat(size, CV_MAKETYPE(CV_32F, cn)); cv::Mat templ = randomMat(templ_size, CV_MAKETYPE(CV_32F, cn)); + cv::Ptr alg = cv::gpu::createTemplateMatching(image.type(), method); + cv::gpu::GpuMat dst; - cv::gpu::matchTemplate(loadMat(image), loadMat(templ), dst, method); + alg->match(loadMat(image), loadMat(templ), dst); cv::Mat dst_gold; cv::matchTemplate(image, templ, dst_gold, method); @@ -169,8 +173,10 @@ GPU_TEST_P(MatchTemplateBlackSource, Accuracy) cv::Mat pattern = readImage("matchtemplate/cat.png"); ASSERT_FALSE(pattern.empty()); + cv::Ptr alg = cv::gpu::createTemplateMatching(image.type(), method); + cv::gpu::GpuMat d_dst; - cv::gpu::matchTemplate(loadMat(image), loadMat(pattern), d_dst, method); + alg->match(loadMat(image), loadMat(pattern), d_dst); cv::Mat dst(d_dst); @@ -214,8 +220,10 @@ GPU_TEST_P(MatchTemplate_CCOEF_NORMED, Accuracy) cv::Mat pattern = readImage(patternName); ASSERT_FALSE(pattern.empty()); + cv::Ptr alg = cv::gpu::createTemplateMatching(image.type(), cv::TM_CCOEFF_NORMED); + cv::gpu::GpuMat d_dst; - cv::gpu::matchTemplate(loadMat(image), loadMat(pattern), d_dst, cv::TM_CCOEFF_NORMED); + alg->match(loadMat(image), loadMat(pattern), d_dst); cv::Mat dst(d_dst); @@ -263,8 +271,10 @@ GPU_TEST_P(MatchTemplate_CanFindBigTemplate, SQDIFF_NORMED) cv::Mat templ = readImage("matchtemplate/template.png"); ASSERT_FALSE(templ.empty()); + cv::Ptr alg = cv::gpu::createTemplateMatching(scene.type(), cv::TM_SQDIFF_NORMED); + cv::gpu::GpuMat d_result; - cv::gpu::matchTemplate(loadMat(scene), loadMat(templ), d_result, cv::TM_SQDIFF_NORMED); + alg->match(loadMat(scene), loadMat(templ), d_result); cv::Mat result(d_result); @@ -286,8 +296,10 @@ GPU_TEST_P(MatchTemplate_CanFindBigTemplate, SQDIFF) cv::Mat templ = readImage("matchtemplate/template.png"); ASSERT_FALSE(templ.empty()); + cv::Ptr alg = cv::gpu::createTemplateMatching(scene.type(), cv::TM_SQDIFF); + cv::gpu::GpuMat d_result; - cv::gpu::matchTemplate(loadMat(scene), loadMat(templ), d_result, cv::TM_SQDIFF); + alg->match(loadMat(scene), loadMat(templ), d_result); cv::Mat result(d_result); diff --git a/modules/gpuimgproc/test/test_precomp.cpp b/modules/gpuimgproc/test/test_precomp.cpp deleted file mode 100644 index 0fb652180..000000000 --- a/modules/gpuimgproc/test/test_precomp.cpp +++ /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 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" diff --git a/modules/gpuimgproc/test/test_precomp.hpp b/modules/gpuimgproc/test/test_precomp.hpp index 4196aa9fe..7a8b1cbcd 100644 --- a/modules/gpuimgproc/test/test_precomp.hpp +++ b/modules/gpuimgproc/test/test_precomp.hpp @@ -55,7 +55,8 @@ #include "opencv2/ts/gpu_test.hpp" #include "opencv2/gpuimgproc.hpp" -#include "opencv2/gpuarithm.hpp" #include "opencv2/imgproc.hpp" +#include "cvconfig.h" + #endif diff --git a/modules/gpulegacy/include/opencv2/gpulegacy/NCV.hpp b/modules/gpulegacy/include/opencv2/gpulegacy/NCV.hpp index e993c6408..cb84c23ad 100644 --- a/modules/gpulegacy/include/opencv2/gpulegacy/NCV.hpp +++ b/modules/gpulegacy/include/opencv2/gpulegacy/NCV.hpp @@ -126,7 +126,7 @@ typedef int Ncv32s; typedef unsigned int Ncv32u; typedef short Ncv16s; typedef unsigned short Ncv16u; -typedef char Ncv8s; +typedef signed char Ncv8s; typedef unsigned char Ncv8u; typedef float Ncv32f; typedef double Ncv64f; diff --git a/modules/gpulegacy/src/cuda/NCVHaarObjectDetection.cu b/modules/gpulegacy/src/cuda/NCVHaarObjectDetection.cu index c8aaaeace..3ac1e9491 100644 --- a/modules/gpulegacy/src/cuda/NCVHaarObjectDetection.cu +++ b/modules/gpulegacy/src/cuda/NCVHaarObjectDetection.cu @@ -2138,8 +2138,8 @@ static NCVStatus loadFromXML(const cv::String &filename, haarClassifierNodes.resize(0); haarFeatures.resize(0); - cv::Ptr oldCascade = (CvHaarClassifierCascade*)cvLoad(filename.c_str(), 0, 0, 0); - if (oldCascade.empty()) + cv::Ptr oldCascade((CvHaarClassifierCascade*)cvLoad(filename.c_str(), 0, 0, 0)); + if (!oldCascade) { return NCV_HAAR_XML_LOADING_EXCEPTION; } diff --git a/modules/gpulegacy/src/cuda/NCVPixelOperations.hpp b/modules/gpulegacy/src/cuda/NCVPixelOperations.hpp index 6409fab94..5cf902a9f 100644 --- a/modules/gpulegacy/src/cuda/NCVPixelOperations.hpp +++ b/modules/gpulegacy/src/cuda/NCVPixelOperations.hpp @@ -51,7 +51,7 @@ template inline __host__ __device__ TBase _pixMaxVal(); template<> static inline __host__ __device__ Ncv8u _pixMaxVal() {return UCHAR_MAX;} template<> static inline __host__ __device__ Ncv16u _pixMaxVal() {return USHRT_MAX;} template<> static inline __host__ __device__ Ncv32u _pixMaxVal() {return UINT_MAX;} -template<> static inline __host__ __device__ Ncv8s _pixMaxVal() {return CHAR_MAX;} +template<> static inline __host__ __device__ Ncv8s _pixMaxVal() {return SCHAR_MAX;} template<> static inline __host__ __device__ Ncv16s _pixMaxVal() {return SHRT_MAX;} template<> static inline __host__ __device__ Ncv32s _pixMaxVal() {return INT_MAX;} template<> static inline __host__ __device__ Ncv32f _pixMaxVal() {return FLT_MAX;} @@ -61,7 +61,7 @@ template inline __host__ __device__ TBase _pixMinVal(); template<> static inline __host__ __device__ Ncv8u _pixMinVal() {return 0;} template<> static inline __host__ __device__ Ncv16u _pixMinVal() {return 0;} template<> static inline __host__ __device__ Ncv32u _pixMinVal() {return 0;} -template<> static inline __host__ __device__ Ncv8s _pixMinVal() {return CHAR_MIN;} +template<> static inline __host__ __device__ Ncv8s _pixMinVal() {return SCHAR_MIN;} template<> static inline __host__ __device__ Ncv16s _pixMinVal() {return SHRT_MIN;} template<> static inline __host__ __device__ Ncv32s _pixMinVal() {return INT_MIN;} template<> static inline __host__ __device__ Ncv32f _pixMinVal() {return FLT_MIN;} diff --git a/modules/gpulegacy/src/precomp.cpp b/modules/gpulegacy/src/precomp.cpp deleted file mode 100644 index 3c01a2596..000000000 --- a/modules/gpulegacy/src/precomp.cpp +++ /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 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" diff --git a/modules/gpulegacy/test/test_precomp.cpp b/modules/gpulegacy/test/test_precomp.cpp deleted file mode 100644 index 0fb652180..000000000 --- a/modules/gpulegacy/test/test_precomp.cpp +++ /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 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" diff --git a/modules/gpulegacy/test/test_precomp.hpp b/modules/gpulegacy/test/test_precomp.hpp index 90485a90a..e1f2d5def 100644 --- a/modules/gpulegacy/test/test_precomp.hpp +++ b/modules/gpulegacy/test/test_precomp.hpp @@ -74,6 +74,8 @@ #include "opencv2/core/private.gpu.hpp" +#include "cvconfig.h" + #include "NCVTest.hpp" #include "NCVAutoTestLister.hpp" #include "NCVTestSourceProvider.hpp" diff --git a/modules/gpuoptflow/doc/optflow.rst b/modules/gpuoptflow/doc/optflow.rst index 5962b2b81..937b209ae 100644 --- a/modules/gpuoptflow/doc/optflow.rst +++ b/modules/gpuoptflow/doc/optflow.rst @@ -3,6 +3,10 @@ Optical Flow .. highlight:: cpp +.. note:: + + * A general optical flow example can be found at opencv_source_code/samples/gpu/optical_flow.cpp + * A general optical flow example using the Nvidia API can be found at opencv_source_code/samples/gpu/opticalflow_nvidia_api.cpp gpu::BroxOpticalFlow @@ -44,6 +48,9 @@ Class computing the optical flow for two images using Brox et al Optical Flow al GpuMat buf; }; +.. note:: + + * An example illustrating the Brox et al optical flow algorithm can be found at opencv_source_code/samples/gpu/brox_optical_flow.cpp gpu::FarnebackOpticalFlow @@ -138,6 +145,9 @@ The class can calculate an optical flow for a sparse feature set or dense optica .. seealso:: :ocv:func:`calcOpticalFlowPyrLK` +.. note:: + + * An example of the Lucas Kanade optical flow algorithm can be found at opencv_source_code/samples/gpu/pyrlk_optical_flow.cpp gpu::PyrLKOpticalFlow::sparse diff --git a/modules/gpuoptflow/perf/perf_main.cpp b/modules/gpuoptflow/perf/perf_main.cpp index dad5e52bb..e261932f8 100644 --- a/modules/gpuoptflow/perf/perf_main.cpp +++ b/modules/gpuoptflow/perf/perf_main.cpp @@ -44,4 +44,4 @@ using namespace perf; -CV_PERF_TEST_MAIN(gpuoptflow, printCudaInfo()) +CV_PERF_TEST_CUDA_MAIN(gpuoptflow) diff --git a/modules/gpuoptflow/perf/perf_optflow.cpp b/modules/gpuoptflow/perf/perf_optflow.cpp index 545225d62..562eb4b20 100644 --- a/modules/gpuoptflow/perf/perf_optflow.cpp +++ b/modules/gpuoptflow/perf/perf_optflow.cpp @@ -368,8 +368,8 @@ PERF_TEST_P(ImagePair, OpticalFlowDual_TVL1, TEST_CYCLE() d_alg(d_frame0, d_frame1, u, v); - GPU_SANITY_CHECK(u, 1e-2); - GPU_SANITY_CHECK(v, 1e-2); + GPU_SANITY_CHECK(u, 1e-1); + GPU_SANITY_CHECK(v, 1e-1); } else { diff --git a/modules/gpuoptflow/perf/perf_precomp.cpp b/modules/gpuoptflow/perf/perf_precomp.cpp deleted file mode 100644 index 81f16e8f1..000000000 --- a/modules/gpuoptflow/perf/perf_precomp.cpp +++ /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 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" diff --git a/modules/gpuoptflow/src/cuda/needle_map.cu b/modules/gpuoptflow/src/cuda/needle_map.cu index d361bcfc6..e0b1ef6b7 100644 --- a/modules/gpuoptflow/src/cuda/needle_map.cu +++ b/modules/gpuoptflow/src/cuda/needle_map.cu @@ -140,7 +140,7 @@ namespace cv { namespace gpu { namespace cudev const float u_avg_val = u_avg(y, x); const float v_avg_val = v_avg(y, x); - const float theta = ::atan2f(v_avg_val, u_avg_val);// + CV_PI; + const float theta = ::atan2f(v_avg_val, u_avg_val); float r = ::sqrtf(v_avg_val * v_avg_val + u_avg_val * u_avg_val); r = fmin(14.0f * (r / max_flow), 14.0f); diff --git a/modules/gpuoptflow/src/cuda/tvl1flow.cu b/modules/gpuoptflow/src/cuda/tvl1flow.cu index 3d1c61264..75d30a624 100644 --- a/modules/gpuoptflow/src/cuda/tvl1flow.cu +++ b/modules/gpuoptflow/src/cuda/tvl1flow.cu @@ -211,7 +211,7 @@ namespace tvl1flow const PtrStepf grad, const PtrStepf rho_c, const PtrStepf p11, const PtrStepf p12, const PtrStepf p21, const PtrStepf p22, PtrStepf u1, PtrStepf u2, PtrStepf error, - const float l_t, const float theta) + const float l_t, const float theta, const bool calcError) { const int x = blockIdx.x * blockDim.x + threadIdx.x; const int y = blockIdx.y * blockDim.y + threadIdx.y; @@ -265,21 +265,24 @@ namespace tvl1flow u1(y, x) = u1NewVal; u2(y, x) = u2NewVal; - const float n1 = (u1OldVal - u1NewVal) * (u1OldVal - u1NewVal); - const float n2 = (u2OldVal - u2NewVal) * (u2OldVal - u2NewVal); - error(y, x) = n1 + n2; + if (calcError) + { + const float n1 = (u1OldVal - u1NewVal) * (u1OldVal - u1NewVal); + const float n2 = (u2OldVal - u2NewVal) * (u2OldVal - u2NewVal); + error(y, x) = n1 + n2; + } } void estimateU(PtrStepSzf I1wx, PtrStepSzf I1wy, PtrStepSzf grad, PtrStepSzf rho_c, PtrStepSzf p11, PtrStepSzf p12, PtrStepSzf p21, PtrStepSzf p22, PtrStepSzf u1, PtrStepSzf u2, PtrStepSzf error, - float l_t, float theta) + float l_t, float theta, bool calcError) { const dim3 block(32, 8); const dim3 grid(divUp(I1wx.cols, block.x), divUp(I1wx.rows, block.y)); - estimateUKernel<<>>(I1wx, I1wy, grad, rho_c, p11, p12, p21, p22, u1, u2, error, l_t, theta); + estimateUKernel<<>>(I1wx, I1wy, grad, rho_c, p11, p12, p21, p22, u1, u2, error, l_t, theta, calcError); cudaSafeCall( cudaGetLastError() ); cudaSafeCall( cudaDeviceSynchronize() ); diff --git a/modules/gpuoptflow/src/needle_map.cpp b/modules/gpuoptflow/src/needle_map.cpp index 1fdc16262..9ca8fe5e4 100644 --- a/modules/gpuoptflow/src/needle_map.cpp +++ b/modules/gpuoptflow/src/needle_map.cpp @@ -94,7 +94,7 @@ void cv::gpu::createOpticalFlowNeedleMap(const GpuMat& u, const GpuMat& v, GpuMa CreateOpticalFlowNeedleMap_gpu(u_avg, v_avg, vertex.ptr(), colors.ptr(), max_flow, 1.0f / u.cols, 1.0f / u.rows); - cvtColor(colors, colors, COLOR_HSV2RGB); + gpu::cvtColor(colors, colors, COLOR_HSV2RGB); } #endif /* HAVE_CUDA */ diff --git a/modules/gpuoptflow/src/precomp.cpp b/modules/gpuoptflow/src/precomp.cpp deleted file mode 100644 index 3c01a2596..000000000 --- a/modules/gpuoptflow/src/precomp.cpp +++ /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 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" diff --git a/modules/gpuoptflow/src/tvl1flow.cpp b/modules/gpuoptflow/src/tvl1flow.cpp index e725e0f27..50b280157 100644 --- a/modules/gpuoptflow/src/tvl1flow.cpp +++ b/modules/gpuoptflow/src/tvl1flow.cpp @@ -173,7 +173,7 @@ namespace tvl1flow PtrStepSzf grad, PtrStepSzf rho_c, PtrStepSzf p11, PtrStepSzf p12, PtrStepSzf p21, PtrStepSzf p22, PtrStepSzf u1, PtrStepSzf u2, PtrStepSzf error, - float l_t, float theta); + float l_t, float theta, bool calcError); void estimateDualVariables(PtrStepSzf u1, PtrStepSzf u2, PtrStepSzf p11, PtrStepSzf p12, PtrStepSzf p21, PtrStepSzf p22, float taut); } @@ -218,11 +218,24 @@ void cv::gpu::OpticalFlowDual_TVL1_GPU::procOneScale(const GpuMat& I0, const Gpu warpBackward(I0, I1, I1x, I1y, u1, u2, I1w, I1wx, I1wy, grad, rho_c); double error = std::numeric_limits::max(); + double prevError = 0.0; for (int n = 0; error > scaledEpsilon && n < iterations; ++n) { - estimateU(I1wx, I1wy, grad, rho_c, p11, p12, p21, p22, u1, u2, diff, l_t, static_cast(theta)); + // some tweaks to make sum operation less frequently + bool calcError = (epsilon > 0) && (n & 0x1) && (prevError < scaledEpsilon); - error = gpu::sum(diff, norm_buf)[0]; + estimateU(I1wx, I1wy, grad, rho_c, p11, p12, p21, p22, u1, u2, diff, l_t, static_cast(theta), calcError); + + if (calcError) + { + error = gpu::sum(diff, norm_buf)[0]; + prevError = error; + } + else + { + error = std::numeric_limits::max(); + prevError -= scaledEpsilon; + } estimateDualVariables(u1, u2, p11, p12, p21, p22, taut); } diff --git a/modules/gpuoptflow/test/test_optflow.cpp b/modules/gpuoptflow/test/test_optflow.cpp index c20260e19..fce07551d 100644 --- a/modules/gpuoptflow/test/test_optflow.cpp +++ b/modules/gpuoptflow/test/test_optflow.cpp @@ -80,7 +80,7 @@ GPU_TEST_P(BroxOpticalFlow, Regression) brox(loadMat(frame0), loadMat(frame1), u, v); std::string fname(cvtest::TS::ptr()->get_data_path()); - if (devInfo.major() >= 2) + if (devInfo.majorVersion() >= 2) fname += "opticalflow/brox_optical_flow_cc20.bin"; else fname += "opticalflow/brox_optical_flow.bin"; diff --git a/modules/gpuoptflow/test/test_precomp.cpp b/modules/gpuoptflow/test/test_precomp.cpp deleted file mode 100644 index 0fb652180..000000000 --- a/modules/gpuoptflow/test/test_precomp.cpp +++ /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 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" diff --git a/modules/gpuoptflow/test/test_precomp.hpp b/modules/gpuoptflow/test/test_precomp.hpp index 32a7443e8..afac60d87 100644 --- a/modules/gpuoptflow/test/test_precomp.hpp +++ b/modules/gpuoptflow/test/test_precomp.hpp @@ -59,4 +59,6 @@ #include "opencv2/gpuoptflow.hpp" #include "opencv2/video.hpp" +#include "cvconfig.h" + #endif diff --git a/modules/gpustereo/doc/stereo.rst b/modules/gpustereo/doc/stereo.rst index 4064fe0a3..f87d43ff8 100644 --- a/modules/gpustereo/doc/stereo.rst +++ b/modules/gpustereo/doc/stereo.rst @@ -3,7 +3,11 @@ Stereo Correspondence .. highlight:: cpp +.. note:: + * A basic stereo matching example can be found at opencv_source_code/samples/gpu/stereo_match.cpp + * A stereo matching example using several GPU's can be found at opencv_source_code/samples/gpu/stereo_multi.cpp + * A stereo matching example using several GPU's and driver API can be found at opencv_source_code/samples/gpu/driver_api_stereo_multi.cpp gpu::StereoBM ------------- diff --git a/modules/gpustereo/perf/perf_main.cpp b/modules/gpustereo/perf/perf_main.cpp index d681cdb4d..0766ccf05 100644 --- a/modules/gpustereo/perf/perf_main.cpp +++ b/modules/gpustereo/perf/perf_main.cpp @@ -44,4 +44,4 @@ using namespace perf; -CV_PERF_TEST_MAIN(gpustereo, printCudaInfo()) +CV_PERF_TEST_CUDA_MAIN(gpustereo) diff --git a/modules/gpustereo/perf/perf_precomp.cpp b/modules/gpustereo/perf/perf_precomp.cpp deleted file mode 100644 index 81f16e8f1..000000000 --- a/modules/gpustereo/perf/perf_precomp.cpp +++ /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 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" diff --git a/modules/gpustereo/src/disparity_bilateral_filter.cpp b/modules/gpustereo/src/disparity_bilateral_filter.cpp index 689a9e76e..9808b7f66 100644 --- a/modules/gpustereo/src/disparity_bilateral_filter.cpp +++ b/modules/gpustereo/src/disparity_bilateral_filter.cpp @@ -200,7 +200,7 @@ namespace Ptr cv::gpu::createDisparityBilateralFilter(int ndisp, int radius, int iters) { - return new DispBilateralFilterImpl(ndisp, radius, iters); + return makePtr(ndisp, radius, iters); } #endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpustereo/src/precomp.cpp b/modules/gpustereo/src/precomp.cpp deleted file mode 100644 index 3c01a2596..000000000 --- a/modules/gpustereo/src/precomp.cpp +++ /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 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" diff --git a/modules/gpustereo/src/stereobm.cpp b/modules/gpustereo/src/stereobm.cpp index 9b32cf7e9..2ef896d57 100644 --- a/modules/gpustereo/src/stereobm.cpp +++ b/modules/gpustereo/src/stereobm.cpp @@ -98,8 +98,8 @@ namespace int getPreFilterCap() const { return preFilterCap_; } void setPreFilterCap(int preFilterCap) { preFilterCap_ = preFilterCap; } - int getTextureThreshold() const { return avergeTexThreshold_; } - void setTextureThreshold(int textureThreshold) { avergeTexThreshold_ = textureThreshold; } + int getTextureThreshold() const { return static_cast(avergeTexThreshold_); } + void setTextureThreshold(int textureThreshold) { avergeTexThreshold_ = static_cast(textureThreshold); } int getUniquenessRatio() const { return 0; } void setUniquenessRatio(int /*uniquenessRatio*/) {} @@ -179,7 +179,7 @@ namespace Ptr cv::gpu::createStereoBM(int numDisparities, int blockSize) { - return new StereoBMImpl(numDisparities, blockSize); + return makePtr(numDisparities, blockSize); } #endif /* !defined (HAVE_CUDA) */ diff --git a/modules/gpustereo/src/stereobp.cpp b/modules/gpustereo/src/stereobp.cpp index ac3bcfe33..f1ea9adf4 100644 --- a/modules/gpustereo/src/stereobp.cpp +++ b/modules/gpustereo/src/stereobp.cpp @@ -361,7 +361,7 @@ namespace Ptr cv::gpu::createStereoBeliefPropagation(int ndisp, int iters, int levels, int msg_type) { - return new StereoBPImpl(ndisp, iters, levels, msg_type); + return makePtr(ndisp, iters, levels, msg_type); } void cv::gpu::StereoBeliefPropagation::estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels) diff --git a/modules/gpustereo/src/stereocsbp.cpp b/modules/gpustereo/src/stereocsbp.cpp index 9afd8d14e..b1135b276 100644 --- a/modules/gpustereo/src/stereocsbp.cpp +++ b/modules/gpustereo/src/stereocsbp.cpp @@ -366,7 +366,7 @@ namespace Ptr cv::gpu::createStereoConstantSpaceBP(int ndisp, int iters, int levels, int nr_plane, int msg_type) { - return new StereoCSBPImpl(ndisp, iters, levels, nr_plane, msg_type); + return makePtr(ndisp, iters, levels, nr_plane, msg_type); } void cv::gpu::StereoConstantSpaceBP::estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels, int& nr_plane) diff --git a/modules/gpustereo/test/test_precomp.cpp b/modules/gpustereo/test/test_precomp.cpp deleted file mode 100644 index 0fb652180..000000000 --- a/modules/gpustereo/test/test_precomp.cpp +++ /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 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" diff --git a/modules/gpustereo/test/test_precomp.hpp b/modules/gpustereo/test/test_precomp.hpp index d55b1ec0d..eb34fcb56 100644 --- a/modules/gpustereo/test/test_precomp.hpp +++ b/modules/gpustereo/test/test_precomp.hpp @@ -57,4 +57,6 @@ #include "opencv2/gpustereo.hpp" #include "opencv2/calib3d.hpp" +#include "cvconfig.h" + #endif diff --git a/modules/gpuwarping/doc/warping.rst b/modules/gpuwarping/doc/warping.rst index b2c95e2b0..5c88eb772 100644 --- a/modules/gpuwarping/doc/warping.rst +++ b/modules/gpuwarping/doc/warping.rst @@ -9,7 +9,7 @@ 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() ) +.. ocv:function:: void gpu::remap(InputArray src, OutputArray dst, InputArray xmap, InputArray ymap, int interpolation, int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar(), Stream& stream = Stream::Null()) :param src: Source image. @@ -43,7 +43,7 @@ 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()) +.. ocv:function:: void gpu::resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation = INTER_LINEAR, Stream& stream = Stream::Null()) :param src: Source image. @@ -80,7 +80,7 @@ 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() ) +.. ocv:function:: void gpu::warpAffine(InputArray src, OutputArray dst, InputArray 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. @@ -102,7 +102,7 @@ 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()) +.. ocv:function:: void gpu::buildWarpAffineMaps(InputArray M, bool inverse, Size dsize, OutputArray xmap, OutputArray ymap, Stream& stream = Stream::Null()) :param M: *2x3* transformation matrix. @@ -124,7 +124,7 @@ 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() ) +.. ocv:function:: void gpu::warpPerspective(InputArray src, OutputArray dst, InputArray 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. @@ -146,7 +146,7 @@ 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()) +.. ocv:function:: void gpu::buildWarpAffineMaps(InputArray M, bool inverse, Size dsize, OutputArray xmap, OutputArray ymap, Stream& stream = Stream::Null()) :param M: *3x3* transformation matrix. @@ -164,11 +164,41 @@ Builds transformation maps for perspective transformation. +gpu::buildWarpPlaneMaps +----------------------- +Builds plane warping maps. + +.. ocv:function:: void gpu::buildWarpPlaneMaps(Size src_size, Rect dst_roi, InputArray K, InputArray R, InputArray T, float scale, OutputArray map_x, OutputArray 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, InputArray K, InputArray R, float scale, OutputArray map_x, OutputArray 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, InputArray K, InputArray R, float scale, OutputArray map_x, OutputArray map_y, Stream& stream = Stream::Null()) + + :param stream: Stream for the asynchronous version. + + + 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()) +.. ocv:function:: void gpu::rotate(InputArray src, OutputArray 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. @@ -190,41 +220,11 @@ Rotates an image around the origin (0,0) and then shifts it. -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()) +.. ocv:function:: void gpu::pyrDown(InputArray src, OutputArray dst, Stream& stream = Stream::Null()) :param src: Source image. @@ -240,7 +240,7 @@ gpu::pyrUp ------------------- Upsamples an image and then smoothes it. -.. ocv:function:: void gpu::pyrUp(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()) +.. ocv:function:: void gpu::pyrUp(InputArray src, OutputArray dst, Stream& stream = Stream::Null()) :param src: Source image. diff --git a/modules/gpuwarping/include/opencv2/gpuwarping.hpp b/modules/gpuwarping/include/opencv2/gpuwarping.hpp index 18b42ce60..ed17464ec 100644 --- a/modules/gpuwarping/include/opencv2/gpuwarping.hpp +++ b/modules/gpuwarping/include/opencv2/gpuwarping.hpp @@ -54,78 +54,60 @@ namespace cv { namespace gpu { //! 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, +CV_EXPORTS void remap(InputArray src, OutputArray dst, InputArray xmap, InputArray ymap, int interpolation, int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar(), 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()); +CV_EXPORTS void resize(InputArray src, OutputArray 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, +CV_EXPORTS void warpAffine(InputArray src, OutputArray dst, InputArray 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()); +CV_EXPORTS void buildWarpAffineMaps(InputArray M, bool inverse, Size dsize, OutputArray xmap, OutputArray 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, +CV_EXPORTS void warpPerspective(InputArray src, OutputArray dst, InputArray 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()); +CV_EXPORTS void buildWarpPerspectiveMaps(InputArray M, bool inverse, Size dsize, OutputArray xmap, OutputArray 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()); +CV_EXPORTS void buildWarpPlaneMaps(Size src_size, Rect dst_roi, InputArray K, InputArray R, InputArray T, float scale, + OutputArray map_x, OutputArray 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()); +CV_EXPORTS void buildWarpCylindricalMaps(Size src_size, Rect dst_roi, InputArray K, InputArray R, float scale, + OutputArray map_x, OutputArray 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()); +CV_EXPORTS void buildWarpSphericalMaps(Size src_size, Rect dst_roi, InputArray K, InputArray R, float scale, + OutputArray map_x, OutputArray 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, +CV_EXPORTS void rotate(InputArray src, OutputArray dst, Size dsize, double angle, double xShift = 0, double yShift = 0, int interpolation = INTER_LINEAR, Stream& stream = Stream::Null()); //! smoothes the source image and downsamples it -CV_EXPORTS void pyrDown(const GpuMat& src, GpuMat& dst, Stream& stream = Stream::Null()); +CV_EXPORTS void pyrDown(InputArray src, OutputArray 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()); +CV_EXPORTS void pyrUp(InputArray src, OutputArray dst, Stream& stream = Stream::Null()); -class CV_EXPORTS ImagePyramid +class CV_EXPORTS ImagePyramid : public Algorithm { 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_; + virtual void getLayer(OutputArray outImg, Size outRoi, Stream& stream = Stream::Null()) const = 0; }; +CV_EXPORTS Ptr createImagePyramid(InputArray img, int nLayers = -1, Stream& stream = Stream::Null()); + }} // namespace cv { namespace gpu { #endif /* __OPENCV_GPUWARPING_HPP__ */ diff --git a/modules/gpuwarping/perf/perf_main.cpp b/modules/gpuwarping/perf/perf_main.cpp index a7c1d5c85..8566b097d 100644 --- a/modules/gpuwarping/perf/perf_main.cpp +++ b/modules/gpuwarping/perf/perf_main.cpp @@ -44,4 +44,4 @@ using namespace perf; -CV_PERF_TEST_MAIN(gpuwarping, printCudaInfo()) +CV_PERF_TEST_CUDA_MAIN(gpuwarping) diff --git a/modules/gpuwarping/perf/perf_precomp.cpp b/modules/gpuwarping/perf/perf_precomp.cpp deleted file mode 100644 index 81f16e8f1..000000000 --- a/modules/gpuwarping/perf/perf_precomp.cpp +++ /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 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" diff --git a/modules/gpuwarping/perf/perf_warping.cpp b/modules/gpuwarping/perf/perf_warping.cpp index fd555cbe5..266475bb0 100644 --- a/modules/gpuwarping/perf/perf_warping.cpp +++ b/modules/gpuwarping/perf/perf_warping.cpp @@ -515,45 +515,6 @@ PERF_TEST_P(Sz_Depth_Cn, PyrUp, } } -////////////////////////////////////////////////////////////////////// -// ImagePyramidBuild - -PERF_TEST_P(Sz_Depth_Cn, 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 @@ -579,9 +540,9 @@ PERF_TEST_P(Sz_Depth_Cn, ImagePyramidGetLayer, const cv::gpu::GpuMat d_src(src); cv::gpu::GpuMat dst; - cv::gpu::ImagePyramid d_pyr(d_src, nLayers); + cv::Ptr d_pyr = cv::gpu::createImagePyramid(d_src, nLayers); - TEST_CYCLE() d_pyr.getLayer(dst, dstSize); + TEST_CYCLE() d_pyr->getLayer(dst, dstSize); GPU_SANITY_CHECK(dst); } diff --git a/modules/gpuwarping/src/cuda/resize.cu b/modules/gpuwarping/src/cuda/resize.cu index 04c1fb2ac..94422db9d 100644 --- a/modules/gpuwarping/src/cuda/resize.cu +++ b/modules/gpuwarping/src/cuda/resize.cu @@ -49,254 +49,434 @@ #include "opencv2/core/cuda/vec_math.hpp" #include "opencv2/core/cuda/saturate_cast.hpp" #include "opencv2/core/cuda/filters.hpp" -#include "opencv2/core/cuda/scan.hpp" namespace cv { namespace gpu { namespace cudev { - namespace imgproc + // kernels + + template __global__ void resize_nearest(const PtrStep src, PtrStepSz dst, const float fy, const float fx) { - template __global__ void resize(const Ptr2D src, float fx, float fy, PtrStepSz dst) + const int dst_x = blockDim.x * blockIdx.x + threadIdx.x; + const int dst_y = blockDim.y * blockIdx.y + threadIdx.y; + + if (dst_x < dst.cols && dst_y < dst.rows) { - const int x = blockDim.x * blockIdx.x + threadIdx.x; - const int y = blockDim.y * blockIdx.y + threadIdx.y; + const float src_x = dst_x * fx; + const float src_y = dst_y * fy; - if (x < dst.cols && y < dst.rows) - { - const float xcoo = x * fx; - const float ycoo = y * fy; - - dst(y, x) = saturate_cast(src(ycoo, xcoo)); - } + dst(dst_y, dst_x) = src(__float2int_rz(src_y), __float2int_rz(src_x)); } + } - template __global__ void resize_area(const Ptr2D src, float fx, float fy, PtrStepSz dst) + template __global__ void resize_linear(const PtrStepSz src, PtrStepSz dst, const float fy, const float fx) + { + typedef typename TypeVec::cn>::vec_type work_type; + + const int dst_x = blockDim.x * blockIdx.x + threadIdx.x; + const int dst_y = blockDim.y * blockIdx.y + threadIdx.y; + + if (dst_x < dst.cols && dst_y < dst.rows) { - const int x = blockDim.x * blockIdx.x + threadIdx.x; - const int y = blockDim.y * blockIdx.y + threadIdx.y; + const float src_x = dst_x * fx; + const float src_y = dst_y * fy; - if (x < dst.cols && y < dst.rows) - { - dst(y, x) = saturate_cast(src(y, x)); - } + work_type out = VecTraits::all(0); + + const int x1 = __float2int_rd(src_x); + const int y1 = __float2int_rd(src_y); + const int x2 = x1 + 1; + const int y2 = y1 + 1; + const int x2_read = ::min(x2, src.cols - 1); + const int y2_read = ::min(y2, src.rows - 1); + + T src_reg = src(y1, x1); + out = out + src_reg * ((x2 - src_x) * (y2 - src_y)); + + src_reg = src(y1, x2_read); + out = out + src_reg * ((src_x - x1) * (y2 - src_y)); + + src_reg = src(y2_read, x1); + out = out + src_reg * ((x2 - src_x) * (src_y - y1)); + + src_reg = src(y2_read, x2_read); + out = out + src_reg * ((src_x - x1) * (src_y - y1)); + + dst(dst_y, dst_x) = saturate_cast(out); } + } - template