From e59912f803c73d62ce08c3b10885a43392a17626 Mon Sep 17 00:00:00 2001 From: StevenPuttemans Date: Thu, 21 Nov 2013 14:07:53 +0100 Subject: [PATCH 01/97] Applied fix mentioned in bugreport 3370. Seems to solve the issue. --- apps/traincascade/imagestorage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/traincascade/imagestorage.cpp b/apps/traincascade/imagestorage.cpp index 0f749f9b01..078b0d02cb 100644 --- a/apps/traincascade/imagestorage.cpp +++ b/apps/traincascade/imagestorage.cpp @@ -67,7 +67,7 @@ bool CvCascadeImageReader::NegReader::nextImg() _offset.x = min( (int)round % winSize.width, src.cols - winSize.width ); _offset.y = min( (int)round / winSize.width, src.rows - winSize.height ); if( !src.empty() && src.type() == CV_8UC1 - && offset.x >= 0 && offset.y >= 0 ) + && _offset.x >= 0 && _offset.y >= 0 ) break; } From 3b4f65b18693b6afebc90bbc46e7f88c28d5f048 Mon Sep 17 00:00:00 2001 From: Eric Sommerlade Date: Tue, 26 Nov 2013 00:12:30 +0000 Subject: [PATCH 02/97] fixed comparison to stop integer wrap around --- modules/imgproc/src/samplers.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/imgproc/src/samplers.cpp b/modules/imgproc/src/samplers.cpp index eb2f61755c..f1c11447bd 100644 --- a/modules/imgproc/src/samplers.cpp +++ b/modules/imgproc/src/samplers.cpp @@ -97,7 +97,7 @@ icvAdjustRect( const void* srcptr, int src_step, int pix_size, rect.x = win_size.width; } - if( ip.x + win_size.width < src_size.width ) + if( ip.x < src_size.width - win_size.width ) rect.width = win_size.width; else { @@ -118,7 +118,7 @@ icvAdjustRect( const void* srcptr, int src_step, int pix_size, else rect.y = -ip.y; - if( ip.y + win_size.height < src_size.height ) + if( ip.y < src_size.height - win_size.height ) rect.height = win_size.height; else { @@ -164,8 +164,8 @@ CvStatus CV_STDCALL icvGetRectSubPix_##flavor##_C1R \ src_step /= sizeof(src[0]); \ dst_step /= sizeof(dst[0]); \ \ - if( 0 <= ip.x && ip.x + win_size.width < src_size.width && \ - 0 <= ip.y && ip.y + win_size.height < src_size.height ) \ + if( 0 <= ip.x && ip.x < src_size.width - win_size.width && \ + 0 <= ip.y && ip.y < src_size.height - win_size.height ) \ { \ /* extracted rectangle is totally inside the image */ \ src += ip.y * src_step + ip.x; \ @@ -270,8 +270,8 @@ static CvStatus CV_STDCALL icvGetRectSubPix_##flavor##_C3R \ src_step /= sizeof( src[0] ); \ dst_step /= sizeof( dst[0] ); \ \ - if( 0 <= ip.x && ip.x + win_size.width < src_size.width && \ - 0 <= ip.y && ip.y + win_size.height < src_size.height ) \ + if( 0 <= ip.x && ip.x < src_size.width - win_size.width && \ + 0 <= ip.y && ip.y < src_size.height - win_size.height ) \ { \ /* extracted rectangle is totally inside the image */ \ src += ip.y * src_step + ip.x*3; \ @@ -407,8 +407,8 @@ CvStatus CV_STDCALL icvGetRectSubPix_8u32f_C1R src_step /= sizeof(src[0]); dst_step /= sizeof(dst[0]); - if( 0 <= ip.x && ip.x + win_size.width < src_size.width && - 0 <= ip.y && ip.y + win_size.height < src_size.height ) + if( 0 <= ip.x && ip.x < src_size.width - win_size.width && + 0 <= ip.y && ip.y < src_size.height - win_size.height ) { // extracted rectangle is totally inside the image src += ip.y * src_step + ip.x; From 735f704b3e85f82df060e0ea00c9c66669287815 Mon Sep 17 00:00:00 2001 From: Philippe FOUBERT Date: Thu, 28 Nov 2013 00:42:19 +0100 Subject: [PATCH 03/97] Add on optional parameter to the matx invert function to know if this operation is successfull without having to analyse the matrix (it may fail in case of bad preconditioning or inappropriate decomposition method) --- modules/core/include/opencv2/core/matx.hpp | 2 +- modules/core/include/opencv2/core/operations.hpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/core/include/opencv2/core/matx.hpp b/modules/core/include/opencv2/core/matx.hpp index 86a35cd756..010e028289 100644 --- a/modules/core/include/opencv2/core/matx.hpp +++ b/modules/core/include/opencv2/core/matx.hpp @@ -154,7 +154,7 @@ public: Matx<_Tp, n, m> t() const; //! invert matrix the matrix - Matx<_Tp, n, m> inv(int method=DECOMP_LU) const; + Matx<_Tp, n, m> inv(int method=DECOMP_LU, bool *p_is_ok = NULL) const; //! solve linear system template Matx<_Tp, n, l> solve(const Matx<_Tp, m, l>& rhs, int flags=DECOMP_LU) const; diff --git a/modules/core/include/opencv2/core/operations.hpp b/modules/core/include/opencv2/core/operations.hpp index f8aeddfb11..ea23f60f12 100644 --- a/modules/core/include/opencv2/core/operations.hpp +++ b/modules/core/include/opencv2/core/operations.hpp @@ -186,7 +186,7 @@ Matx<_Tp,m,n> Matx<_Tp,m,n>::randn(_Tp a, _Tp b) } template inline -Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method) const +Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method, bool *p_is_ok /*= NULL*/) const { Matx<_Tp, n, m> b; bool ok; @@ -197,6 +197,7 @@ Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method) const Mat A(*this, false), B(b, false); ok = (invert(A, B, method) != 0); } + if( NULL != p_is_ok ) { *p_is_ok = ok; } return ok ? b : Matx<_Tp, n, m>::zeros(); } From 22ad487328f75c1c422e33bd3d089c99bdb9ab19 Mon Sep 17 00:00:00 2001 From: Philippe FOUBERT Date: Thu, 28 Nov 2013 00:45:58 +0100 Subject: [PATCH 04/97] Comment correction --- modules/core/include/opencv2/core/matx.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/matx.hpp b/modules/core/include/opencv2/core/matx.hpp index 010e028289..d7d4859573 100644 --- a/modules/core/include/opencv2/core/matx.hpp +++ b/modules/core/include/opencv2/core/matx.hpp @@ -153,7 +153,7 @@ public: //! transpose the matrix Matx<_Tp, n, m> t() const; - //! invert matrix the matrix + //! invert the matrix Matx<_Tp, n, m> inv(int method=DECOMP_LU, bool *p_is_ok = NULL) const; //! solve linear system From 95ebdf4069a6333c14e4a610acc37e11cc90a0da Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Thu, 7 Nov 2013 12:16:06 +0400 Subject: [PATCH 05/97] fixed compilation with CUDA 6.0: GpuMat::setTo function, removed NPP call for CV_8S --- modules/core/src/gpumat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/gpumat.cpp b/modules/core/src/gpumat.cpp index ff459f9a61..4c4af61c47 100644 --- a/modules/core/src/gpumat.cpp +++ b/modules/core/src/gpumat.cpp @@ -1361,7 +1361,7 @@ namespace static const func_t funcs[7][4] = { {NppSet::call, cv::gpu::setTo , cv::gpu::setTo , NppSet::call}, - {NppSet::call, NppSet::call, NppSet::call, NppSet::call}, + {cv::gpu::setTo , cv::gpu::setTo , cv::gpu::setTo , cv::gpu::setTo }, {NppSet::call, NppSet::call, cv::gpu::setTo , NppSet::call}, {NppSet::call, NppSet::call, cv::gpu::setTo , NppSet::call}, {NppSet::call, cv::gpu::setTo , cv::gpu::setTo , NppSet::call}, From 9ce9fc3361decee8ac2381fc0dfcff551927ed7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9verin=20Lemaignan?= Date: Tue, 26 Nov 2013 05:53:44 +0100 Subject: [PATCH 06/97] Ensure compilation to Javascript with Emscripten --- modules/core/include/opencv2/core/operations.hpp | 6 ++++-- modules/core/src/system.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/core/include/opencv2/core/operations.hpp b/modules/core/include/opencv2/core/operations.hpp index 9569d1abc0..4ab7e35f90 100644 --- a/modules/core/include/opencv2/core/operations.hpp +++ b/modules/core/include/opencv2/core/operations.hpp @@ -56,7 +56,7 @@ #define CV_XADD(addr,delta) _InterlockedExchangeAdd(const_cast(reinterpret_cast(addr)), delta) #elif defined __GNUC__ - #if defined __clang__ && __clang_major__ >= 3 && !defined __ANDROID__ + #if defined __clang__ && __clang_major__ >= 3 && !defined __ANDROID__ && !defined __EMSCRIPTEN__ #ifdef __ATOMIC_SEQ_CST #define CV_XADD(addr, delta) __c11_atomic_fetch_add((_Atomic(int)*)(addr), (delta), __ATOMIC_SEQ_CST) #else @@ -66,7 +66,9 @@ #if !(defined WIN32 || defined _WIN32) && (defined __i486__ || defined __i586__ || \ defined __i686__ || defined __MMX__ || defined __SSE__ || defined __ppc__) || \ - (defined __GNUC__ && defined _STLPORT_MAJOR) + (defined __GNUC__ && defined _STLPORT_MAJOR) || \ + defined __EMSCRIPTEN__ + #define CV_XADD __sync_fetch_and_add #else #include diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 88993630ec..88f13d622a 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -126,7 +126,7 @@ std::wstring GetTempFileNameWinRT(std::wstring prefix) #include -#if defined __linux__ || defined __APPLE__ +#if defined __linux__ || defined __APPLE__ || defined __EMSCRIPTEN__ #include #include #include From bd9d3dd561764f4e6993cd0b7b0b1aba7b27b099 Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Tue, 3 Dec 2013 13:16:44 +0400 Subject: [PATCH 07/97] fixing build of 2.4 branch with VC12 (aka 2013) (master branch was fixed before, no need to merge this to master!) - disable openexr (numerous undefined std::min & std::max) - workaround for two compilator bugs --- CMakeLists.txt | 2 +- modules/features2d/src/features2d_init.cpp | 2 +- modules/features2d/src/orb.cpp | 13 ++++++++----- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a7c730bc0..14353dccb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,7 +140,7 @@ OCV_OPTION(WITH_IMAGEIO "ImageIO support for OS X" OFF OCV_OPTION(WITH_IPP "Include Intel IPP support" OFF IF (MSVC OR X86 OR X86_64) ) OCV_OPTION(WITH_JASPER "Include JPEG2K support" ON IF (NOT IOS) ) OCV_OPTION(WITH_JPEG "Include JPEG support" ON) -OCV_OPTION(WITH_OPENEXR "Include ILM support via OpenEXR" ON IF (NOT IOS) ) +OCV_OPTION(WITH_OPENEXR "Include ILM support via OpenEXR" ON IF (NOT IOS AND NOT MSVC12) ) OCV_OPTION(WITH_OPENGL "Include OpenGL support" OFF IF (NOT ANDROID AND NOT APPLE) ) OCV_OPTION(WITH_OPENNI "Include OpenNI support" OFF IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_PNG "Include PNG support" ON) diff --git a/modules/features2d/src/features2d_init.cpp b/modules/features2d/src/features2d_init.cpp index ebac9cb54f..9fcbcd6c59 100644 --- a/modules/features2d/src/features2d_init.cpp +++ b/modules/features2d/src/features2d_init.cpp @@ -181,7 +181,7 @@ CV_INIT_ALGORITHM(DenseFeatureDetector, "Feature2D.Dense", obj.info()->addParam(obj, "varyImgBoundWithScale", obj.varyImgBoundWithScale)); CV_INIT_ALGORITHM(GridAdaptedFeatureDetector, "Feature2D.Grid", - obj.info()->addParam(obj, "detector", obj.detector); + obj.info()->addParam(obj, "detector", (Ptr&)obj.detector); obj.info()->addParam(obj, "maxTotalKeypoints", obj.maxTotalKeypoints); obj.info()->addParam(obj, "gridRows", obj.gridRows); obj.info()->addParam(obj, "gridCols", obj.gridCols)); diff --git a/modules/features2d/src/orb.cpp b/modules/features2d/src/orb.cpp index 8aeea829a8..dd81c5f682 100644 --- a/modules/features2d/src/orb.cpp +++ b/modules/features2d/src/orb.cpp @@ -138,13 +138,16 @@ static void computeOrbDescriptor(const KeyPoint& kpt, const uchar* center = &img.at(cvRound(kpt.pt.y), cvRound(kpt.pt.x)); int step = (int)img.step; -#if 1 - #define GET_VALUE(idx) \ - center[cvRound(pattern[idx].x*b + pattern[idx].y*a)*step + \ - cvRound(pattern[idx].x*a - pattern[idx].y*b)] -#else float x, y; int ix, iy; +#if 1 + #define GET_VALUE(idx) \ + (x = pattern[idx].x*a - pattern[idx].y*b, \ + y = pattern[idx].x*b + pattern[idx].y*a, \ + ix = cvRound(x), \ + iy = cvRound(y), \ + *(center + iy*step + ix) ) +#else #define GET_VALUE(idx) \ (x = pattern[idx].x*a - pattern[idx].y*b, \ y = pattern[idx].x*b + pattern[idx].y*a, \ From 14ee306b9ec7c4dcd09014b8480d85a955c7706f Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Tue, 3 Dec 2013 15:55:10 +0400 Subject: [PATCH 08/97] fix gpu test for Demosaicing: check that input images was loaded correctly --- modules/gpu/test/test_color.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/gpu/test/test_color.cpp b/modules/gpu/test/test_color.cpp index 4bd53c9194..3f5a37fd03 100644 --- a/modules/gpu/test/test_color.cpp +++ b/modules/gpu/test/test_color.cpp @@ -2357,6 +2357,7 @@ struct Demosaicing : testing::TestWithParam GPU_TEST_P(Demosaicing, BayerBG2BGR) { cv::Mat img = readImage("stereobm/aloe-L.png"); + ASSERT_FALSE(img.empty()) << "Can't load input image"; cv::Mat_ src; mosaic(img, src, cv::Point(1, 1)); @@ -2370,6 +2371,7 @@ GPU_TEST_P(Demosaicing, BayerBG2BGR) GPU_TEST_P(Demosaicing, BayerGB2BGR) { cv::Mat img = readImage("stereobm/aloe-L.png"); + ASSERT_FALSE(img.empty()) << "Can't load input image"; cv::Mat_ src; mosaic(img, src, cv::Point(0, 1)); @@ -2383,6 +2385,7 @@ GPU_TEST_P(Demosaicing, BayerGB2BGR) GPU_TEST_P(Demosaicing, BayerRG2BGR) { cv::Mat img = readImage("stereobm/aloe-L.png"); + ASSERT_FALSE(img.empty()) << "Can't load input image"; cv::Mat_ src; mosaic(img, src, cv::Point(0, 0)); @@ -2396,6 +2399,7 @@ GPU_TEST_P(Demosaicing, BayerRG2BGR) GPU_TEST_P(Demosaicing, BayerGR2BGR) { cv::Mat img = readImage("stereobm/aloe-L.png"); + ASSERT_FALSE(img.empty()) << "Can't load input image"; cv::Mat_ src; mosaic(img, src, cv::Point(1, 0)); @@ -2409,6 +2413,7 @@ GPU_TEST_P(Demosaicing, BayerGR2BGR) GPU_TEST_P(Demosaicing, BayerBG2BGR_MHT) { cv::Mat img = readImage("stereobm/aloe-L.png"); + ASSERT_FALSE(img.empty()) << "Can't load input image"; cv::Mat_ src; mosaic(img, src, cv::Point(1, 1)); @@ -2422,6 +2427,7 @@ GPU_TEST_P(Demosaicing, BayerBG2BGR_MHT) GPU_TEST_P(Demosaicing, BayerGB2BGR_MHT) { cv::Mat img = readImage("stereobm/aloe-L.png"); + ASSERT_FALSE(img.empty()) << "Can't load input image"; cv::Mat_ src; mosaic(img, src, cv::Point(0, 1)); @@ -2435,6 +2441,7 @@ GPU_TEST_P(Demosaicing, BayerGB2BGR_MHT) GPU_TEST_P(Demosaicing, BayerRG2BGR_MHT) { cv::Mat img = readImage("stereobm/aloe-L.png"); + ASSERT_FALSE(img.empty()) << "Can't load input image"; cv::Mat_ src; mosaic(img, src, cv::Point(0, 0)); @@ -2448,6 +2455,7 @@ GPU_TEST_P(Demosaicing, BayerRG2BGR_MHT) GPU_TEST_P(Demosaicing, BayerGR2BGR_MHT) { cv::Mat img = readImage("stereobm/aloe-L.png"); + ASSERT_FALSE(img.empty()) << "Can't load input image"; cv::Mat_ src; mosaic(img, src, cv::Point(1, 0)); From adb2040980e61a4bf76675c163c0ada20809a7e2 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Tue, 3 Dec 2013 15:55:47 +0400 Subject: [PATCH 09/97] added additional check in cv::gpu::demosaicing that source is not empty --- modules/gpu/src/color.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gpu/src/color.cpp b/modules/gpu/src/color.cpp index 76793d5200..864c4755ea 100644 --- a/modules/gpu/src/color.cpp +++ b/modules/gpu/src/color.cpp @@ -1863,7 +1863,7 @@ void cv::gpu::demosaicing(const GpuMat& src, GpuMat& dst, int code, int dcn, Str { const int depth = src.depth(); - CV_Assert( src.channels() == 1 ); + CV_Assert( src.channels() == 1 && !src.empty() ); switch (code) { From c962a9d61cffbbc88a61d59449f557d3a2202258 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 3 Dec 2013 16:02:41 +0400 Subject: [PATCH 10/97] ocl:perf: fix moments test for plain impl --- modules/ocl/perf/perf_moments.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ocl/perf/perf_moments.cpp b/modules/ocl/perf/perf_moments.cpp index c5d616f83d..631031ecb4 100644 --- a/modules/ocl/perf/perf_moments.cpp +++ b/modules/ocl/perf/perf_moments.cpp @@ -73,10 +73,10 @@ PERF_TEST_P(MomentsFixture, Moments, Mat src(srcSize, type), dst(7, 1, CV_64F); randu(src, 0, 255); - oclMat src_d(src); cv::Moments mom; if (RUN_OCL_IMPL) { + oclMat src_d(src); OCL_TEST_CYCLE() mom = cv::ocl::ocl_moments(src_d, binaryImage); } else if (RUN_PLAIN_IMPL) From b5dbe9e04bc69e966168a33a5f96f44b7e064502 Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Tue, 3 Dec 2013 16:08:57 +0400 Subject: [PATCH 11/97] Added patch from master for fixing VS2013 in 3rd party lib OpenEXR --- 3rdparty/openexr/IlmImf/ImfAcesFile.cpp | 1 + 3rdparty/openexr/IlmImf/ImfOutputFile.cpp | 1 + .../openexr/IlmImf/ImfScanLineInputFile.cpp | 1 + 3rdparty/openexr/IlmImf/ImfTiledMisc.cpp | 1 + .../openexr/IlmImf/ImfTiledOutputFile.cpp | 1 + 3rdparty/openexr/Imath/ImathMatrixAlgo.cpp | 1 + 3rdparty/openexr/fix_msvc2013_errors.patch | 72 +++++++++++++++++++ CMakeLists.txt | 2 +- 8 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 3rdparty/openexr/fix_msvc2013_errors.patch diff --git a/3rdparty/openexr/IlmImf/ImfAcesFile.cpp b/3rdparty/openexr/IlmImf/ImfAcesFile.cpp index de4bf83c6a..9418b9d2a1 100644 --- a/3rdparty/openexr/IlmImf/ImfAcesFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfAcesFile.cpp @@ -42,6 +42,7 @@ #include #include #include +#include // for std::max() using namespace std; using namespace Imath; diff --git a/3rdparty/openexr/IlmImf/ImfOutputFile.cpp b/3rdparty/openexr/IlmImf/ImfOutputFile.cpp index 8831ec94d1..e69b92bd57 100644 --- a/3rdparty/openexr/IlmImf/ImfOutputFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfOutputFile.cpp @@ -58,6 +58,7 @@ #include #include #include +#include // for std::max() namespace Imf { diff --git a/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp b/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp index f7a12a3476..5d8b52201b 100644 --- a/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp @@ -56,6 +56,7 @@ #include #include #include +#include // for std::max() namespace Imf { diff --git a/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp b/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp index 57f52f17f8..9588e789f6 100644 --- a/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp +++ b/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp @@ -43,6 +43,7 @@ #include "Iex.h" #include #include +#include // for std::max() namespace Imf { diff --git a/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp b/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp index 08821060d8..0bc3cb3c30 100644 --- a/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp @@ -63,6 +63,7 @@ #include #include #include +#include // for std::max() namespace Imf { diff --git a/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp b/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp index f0d2ed679f..7ddc64968f 100644 --- a/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp +++ b/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp @@ -44,6 +44,7 @@ #include "ImathMatrixAlgo.h" #include +#include // for std::max() #if defined(OPENEXR_DLL) #define EXPORT_CONST __declspec(dllexport) diff --git a/3rdparty/openexr/fix_msvc2013_errors.patch b/3rdparty/openexr/fix_msvc2013_errors.patch new file mode 100644 index 0000000000..0ce106f13b --- /dev/null +++ b/3rdparty/openexr/fix_msvc2013_errors.patch @@ -0,0 +1,72 @@ +diff --git a/3rdparty/openexr/IlmImf/ImfAcesFile.cpp b/3rdparty/openexr/IlmImf/ImfAcesFile.cpp +index de4bf83..9418b9d 100644 +--- a/3rdparty/openexr/IlmImf/ImfAcesFile.cpp ++++ b/3rdparty/openexr/IlmImf/ImfAcesFile.cpp +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include // for std::max() + + using namespace std; + using namespace Imath; +diff --git a/3rdparty/openexr/IlmImf/ImfOutputFile.cpp b/3rdparty/openexr/IlmImf/ImfOutputFile.cpp +index 8831ec9..e69b92b 100644 +--- a/3rdparty/openexr/IlmImf/ImfOutputFile.cpp ++++ b/3rdparty/openexr/IlmImf/ImfOutputFile.cpp +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include // for std::max() + + + namespace Imf { +diff --git a/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp b/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp +index f7a12a3..5d8b522 100644 +--- a/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp ++++ b/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp +@@ -56,6 +56,7 @@ + #include + #include + #include ++#include // for std::max() + + + namespace Imf { +diff --git a/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp b/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp +index 57f52f1..9588e78 100644 +--- a/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp ++++ b/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp +@@ -43,6 +43,7 @@ + #include "Iex.h" + #include + #include ++#include // for std::max() + + + namespace Imf { +diff --git a/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp b/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp +index 0882106..0bc3cb3 100644 +--- a/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp ++++ b/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp +@@ -63,6 +63,7 @@ + #include + #include + #include ++#include // for std::max() + + + namespace Imf { +diff --git a/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp b/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp +index f0d2ed6..7ddc649 100644 +--- a/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp ++++ b/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp +@@ -44,6 +44,7 @@ + + #include "ImathMatrixAlgo.h" + #include ++#include // for std::max() + + #if defined(OPENEXR_DLL) + #define EXPORT_CONST __declspec(dllexport) diff --git a/CMakeLists.txt b/CMakeLists.txt index 14353dccb6..2a7c730bc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,7 +140,7 @@ OCV_OPTION(WITH_IMAGEIO "ImageIO support for OS X" OFF OCV_OPTION(WITH_IPP "Include Intel IPP support" OFF IF (MSVC OR X86 OR X86_64) ) OCV_OPTION(WITH_JASPER "Include JPEG2K support" ON IF (NOT IOS) ) OCV_OPTION(WITH_JPEG "Include JPEG support" ON) -OCV_OPTION(WITH_OPENEXR "Include ILM support via OpenEXR" ON IF (NOT IOS AND NOT MSVC12) ) +OCV_OPTION(WITH_OPENEXR "Include ILM support via OpenEXR" ON IF (NOT IOS) ) OCV_OPTION(WITH_OPENGL "Include OpenGL support" OFF IF (NOT ANDROID AND NOT APPLE) ) OCV_OPTION(WITH_OPENNI "Include OpenNI support" OFF IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_PNG "Include PNG support" ON) From 2b3105591446cabbf13a1bc7ac26b1f6ca397af9 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Tue, 3 Dec 2013 17:33:28 +0400 Subject: [PATCH 12/97] Fixed the "platfrom" typo everywhere. --- .../arm_crosscompile_with_cmake.rst | 2 +- .../engine/jni/NativeService/PackageInfo.cpp | 4 ++-- .../engine/jni/Tests/HardwareDetectionTest.cpp | 2 +- .../org/opencv/engine/manager/ManagerActivity.java | 14 +++++++------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/tutorials/introduction/crosscompilation/arm_crosscompile_with_cmake.rst b/doc/tutorials/introduction/crosscompilation/arm_crosscompile_with_cmake.rst index c40b86c974..0b2253acea 100644 --- a/doc/tutorials/introduction/crosscompilation/arm_crosscompile_with_cmake.rst +++ b/doc/tutorials/introduction/crosscompilation/arm_crosscompile_with_cmake.rst @@ -105,7 +105,7 @@ Building OpenCV Enable hardware optimizations ----------------------------- -Depending on target platfrom architecture different instruction sets can be used. By default +Depending on target platform architecture different instruction sets can be used. By default compiler generates code for armv5l without VFPv3 and NEON extensions. Add ``-DUSE_VFPV3=ON`` to cmake command line to enable code generation for VFPv3 and ``-DUSE_NEON=ON`` for using NEON SIMD extensions. diff --git a/platforms/android/service/engine/jni/NativeService/PackageInfo.cpp b/platforms/android/service/engine/jni/NativeService/PackageInfo.cpp index 64ea70dae8..98ea828747 100644 --- a/platforms/android/service/engine/jni/NativeService/PackageInfo.cpp +++ b/platforms/android/service/engine/jni/NativeService/PackageInfo.cpp @@ -170,7 +170,7 @@ inline string JoinPlatform(int platform) return result; } -inline int SplitPlatfrom(const vector& features) +inline int SplitPlatform(const vector& features) { int result = 0; @@ -419,7 +419,7 @@ InstallPath(install_path) return; } - Platform = SplitPlatfrom(features); + Platform = SplitPlatform(features); if (PLATFORM_UNKNOWN != Platform) { switch (Platform) diff --git a/platforms/android/service/engine/jni/Tests/HardwareDetectionTest.cpp b/platforms/android/service/engine/jni/Tests/HardwareDetectionTest.cpp index 8637dfee30..83dd9c27e1 100644 --- a/platforms/android/service/engine/jni/Tests/HardwareDetectionTest.cpp +++ b/platforms/android/service/engine/jni/Tests/HardwareDetectionTest.cpp @@ -170,7 +170,7 @@ TEST(CpuID, CheckVFPv3) EXPECT_TRUE(cpu_id & FEATURES_HAS_VFPv3); } -TEST(PlatfromDetector, CheckTegra) +TEST(PlatformDetector, CheckTegra) { EXPECT_NE(PLATFORM_UNKNOWN, DetectKnownPlatforms()); } diff --git a/platforms/android/service/engine/src/org/opencv/engine/manager/ManagerActivity.java b/platforms/android/service/engine/src/org/opencv/engine/manager/ManagerActivity.java index 4e9050fa4d..8e8389dcc7 100644 --- a/platforms/android/service/engine/src/org/opencv/engine/manager/ManagerActivity.java +++ b/platforms/android/service/engine/src/org/opencv/engine/manager/ManagerActivity.java @@ -90,28 +90,28 @@ public class ManagerActivity extends Activity mInstalledPackageView.setAdapter(mInstalledPacksAdapter); TextView HardwarePlatformView = (TextView)findViewById(R.id.HardwareValue); - int Platfrom = HardwareDetector.DetectKnownPlatforms(); + int Platform = HardwareDetector.DetectKnownPlatforms(); int CpuId = HardwareDetector.GetCpuID(); - if (HardwareDetector.PLATFORM_UNKNOWN != Platfrom) + if (HardwareDetector.PLATFORM_UNKNOWN != Platform) { - if (HardwareDetector.PLATFORM_TEGRA == Platfrom) + if (HardwareDetector.PLATFORM_TEGRA == Platform) { HardwarePlatformView.setText("Tegra"); } - else if (HardwareDetector.PLATFORM_TEGRA2 == Platfrom) + else if (HardwareDetector.PLATFORM_TEGRA2 == Platform) { HardwarePlatformView.setText("Tegra 2"); } - else if (HardwareDetector.PLATFORM_TEGRA3 == Platfrom) + else if (HardwareDetector.PLATFORM_TEGRA3 == Platform) { HardwarePlatformView.setText("Tegra 3"); } - else if (HardwareDetector.PLATFORM_TEGRA4i == Platfrom) + else if (HardwareDetector.PLATFORM_TEGRA4i == Platform) { HardwarePlatformView.setText("Tegra 4i"); } - else if (HardwareDetector.PLATFORM_TEGRA4 == Platfrom) + else if (HardwareDetector.PLATFORM_TEGRA4 == Platform) { HardwarePlatformView.setText("Tegra 4"); } From 1966e7cea9d6dd38db39f29f53b4ca96d56ce2d1 Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Tue, 3 Dec 2013 17:46:09 +0400 Subject: [PATCH 13/97] fixing compilation on Linux --- modules/features2d/src/features2d_init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/features2d/src/features2d_init.cpp b/modules/features2d/src/features2d_init.cpp index 9fcbcd6c59..13ef0f8ae5 100644 --- a/modules/features2d/src/features2d_init.cpp +++ b/modules/features2d/src/features2d_init.cpp @@ -181,7 +181,7 @@ CV_INIT_ALGORITHM(DenseFeatureDetector, "Feature2D.Dense", obj.info()->addParam(obj, "varyImgBoundWithScale", obj.varyImgBoundWithScale)); CV_INIT_ALGORITHM(GridAdaptedFeatureDetector, "Feature2D.Grid", - obj.info()->addParam(obj, "detector", (Ptr&)obj.detector); + obj.info()->addParam(obj, "detector", obj.detector, false, 0, 0); // Extra params added to avoid VS2013 fatal error in opencv2/core.hpp (decl. of addParam) obj.info()->addParam(obj, "maxTotalKeypoints", obj.maxTotalKeypoints); obj.info()->addParam(obj, "gridRows", obj.gridRows); obj.info()->addParam(obj, "gridCols", obj.gridCols)); From 11c7053b0f81ad31474b236205ca9fab177f75fc Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Wed, 4 Dec 2013 12:39:20 +0400 Subject: [PATCH 14/97] Fixed a -Wundef warning in cl_platform.h. _MSC_VER -> defined _MSC_VER. Fixes building with MinGW. Similar to fbc91c5ee. --- 3rdparty/include/opencl/1.2/CL/cl_platform.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty/include/opencl/1.2/CL/cl_platform.h b/3rdparty/include/opencl/1.2/CL/cl_platform.h index 46b3d9dcdc..e94949a31c 100644 --- a/3rdparty/include/opencl/1.2/CL/cl_platform.h +++ b/3rdparty/include/opencl/1.2/CL/cl_platform.h @@ -454,7 +454,7 @@ typedef unsigned int cl_GLenum; /* Define alignment keys */ #if defined( __GNUC__ ) #define CL_ALIGNED(_x) __attribute__ ((aligned(_x))) -#elif defined( _WIN32) && (_MSC_VER) +#elif defined( _WIN32) && defined(_MSC_VER) /* Alignment keys neutered on windows because MSVC can't swallow function arguments with alignment requirements */ /* http://msdn.microsoft.com/en-us/library/373ak2y1%28VS.71%29.aspx */ /* #include */ From 7b551af424b9daf576d52190fcbca64c88108e31 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 4 Dec 2013 13:00:37 +0400 Subject: [PATCH 15/97] ocl: try to disable clFinish workaround --- modules/ocl/src/cl_operations.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/ocl/src/cl_operations.cpp b/modules/ocl/src/cl_operations.cpp index 032ebe82a4..0b934074d8 100644 --- a/modules/ocl/src/cl_operations.cpp +++ b/modules/ocl/src/cl_operations.cpp @@ -290,8 +290,9 @@ void openCLFree(void *devPtr) } #else // TODO FIXIT Attach clReleaseMemObject call to event completion callback - Context* ctx = Context::getContext(); - clFinish(getClCommandQueue(ctx)); + // TODO 2013/12/04 Disable workaround + // Context* ctx = Context::getContext(); + // clFinish(getClCommandQueue(ctx)); #endif openCLSafeCall(clReleaseMemObject(data.mainBuffer)); } From 95db69f6b95d5faedf4e4f2116daa1202df28c6e Mon Sep 17 00:00:00 2001 From: siddharth Date: Sat, 15 Jun 2013 16:19:31 +0530 Subject: [PATCH 16/97] added new files --- modules/photo/include/opencv2/photo.hpp | 2 + modules/photo/src/contrast_preserve.cpp | 76 +++++++++++++++++++++++++ modules/photo/src/contrast_preserve.hpp | 31 ++++++++++ 3 files changed, 109 insertions(+) create mode 100644 modules/photo/src/contrast_preserve.cpp create mode 100644 modules/photo/src/contrast_preserve.hpp diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index beec929235..e656b93e8a 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -288,6 +288,8 @@ public: CV_EXPORTS_W Ptr createMergeRobertson(); +CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost); + } // cv #endif diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp new file mode 100644 index 0000000000..271afb5e7e --- /dev/null +++ b/modules/photo/src/contrast_preserve.cpp @@ -0,0 +1,76 @@ +#include "precomp.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "math.h" +#include +#include +#include + +#include "contrast_preserve.hpp" + +using namespace std; +using namespace cv; +int rounding(double); + +int rounding(double a) +{ + return int(a + 0.5); +} + +void cv::decolor(InputArray _src, OutputArray _gray, OutputArray _boost) +{ + Mat I = _src.getMat(); + _gray.create(I.size(), CV_8UC1); + Mat dst = _gray.getMat(); + + _boost.create(I.size(), CV_8UC3); + Mat color_boost = _boost.getMat(); + + if(!I.data ) + { + cout << "Could not open or find the image" << endl ; + return; + } + if(I.channels() !=3) + { + cout << "Input Color Image" << endl; + return; + } + + float sigma = .02; + int maxIter = 8; + int iterCount = 0; + + int h = I.size().height; + int w = I.size().width; + + Mat img; + Decolor obj; + + double sizefactor; + + if((h + w) > 900) + { + sizefactor = (double)900/(h+w); + resize(I,I,Size(rounding(h*sizefactor),rounding(w*sizefactor))); + img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + } + else + { + img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + } + + obj.init(); + + vector Cg; + vector < vector > polyGrad; + vector < vector > bc; + vector < vector < int > > comb; + + vector alf; + + +} + diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp new file mode 100644 index 0000000000..5c6cd50cf9 --- /dev/null +++ b/modules/photo/src/contrast_preserve.hpp @@ -0,0 +1,31 @@ +#include "precomp.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "math.h" +#include +#include + +using namespace std; +using namespace cv; + +class Decolor +{ + public: + Mat kernel; + Mat kernel1; + int order; + void init(); + void grad_system(Mat img, vector < vector < double > > &polyGrad, vector < double > &Cg, vector < vector >& comb); +}; + +void Decolor::init() +{ + kernel = Mat(1,2, CV_32FC1); + kernel1 = Mat(2,1, CV_32FC1); + kernel.at(0,0)=1.0; + kernel.at(0,1)=-1.0; + kernel1.at(0,0)=1.0; + kernel1.at(1,0)=-1.0; + order = 2; + +} From 88aa4a9902dbbf47ee79506996101634cc07881a Mon Sep 17 00:00:00 2001 From: siddharth Date: Mon, 17 Jun 2013 15:27:52 +0530 Subject: [PATCH 17/97] decolor module updated update3 update4 update4 update5 added test data --- modules/photo/include/opencv2/photo.hpp | 2 +- modules/photo/src/contrast_preserve.cpp | 182 ++++++++--- modules/photo/src/contrast_preserve.hpp | 405 +++++++++++++++++++++++- modules/photo/test/test_decolor.cpp | 34 ++ 4 files changed, 568 insertions(+), 55 deletions(-) create mode 100644 modules/photo/test/test_decolor.cpp diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index e656b93e8a..6f5868dd4c 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -288,7 +288,7 @@ public: CV_EXPORTS_W Ptr createMergeRobertson(); -CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost); +CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale); } // cv diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 271afb5e7e..6d4a2d1313 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -5,72 +5,162 @@ #include #include #include - #include "contrast_preserve.hpp" using namespace std; using namespace cv; -int rounding(double); + +int rounding(double a); int rounding(double a) { - return int(a + 0.5); + return int(a + 0.5); } -void cv::decolor(InputArray _src, OutputArray _gray, OutputArray _boost) +void cv::decolor(InputArray _src, OutputArray _dst) { - Mat I = _src.getMat(); - _gray.create(I.size(), CV_8UC1); - Mat dst = _gray.getMat(); + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC1); + Mat dst = _dst.getMat(); - _boost.create(I.size(), CV_8UC3); - Mat color_boost = _boost.getMat(); + if(!I.data ) + { + cout << "Could not open or find the image" << endl ; + return; + } + if(I.channels() !=3) + { + cout << "Input Color Image" << endl; + return; + } - if(!I.data ) - { - cout << "Could not open or find the image" << endl ; - return; - } - if(I.channels() !=3) - { - cout << "Input Color Image" << endl; - return; - } + float sigma = .02; + int maxIter = 8; + int iterCount = 0; - float sigma = .02; - int maxIter = 8; - int iterCount = 0; + int h = I.size().height; + int w = I.size().width; - int h = I.size().height; - int w = I.size().width; + Decolor obj; - Mat img; - Decolor obj; + Mat img; + + double sizefactor; - double sizefactor; + if((h + w) > 900) + { + sizefactor = (double)900/(h+w); + resize(I,I,Size(rounding(h*sizefactor),rounding(w*sizefactor))); + img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + } + else + { + img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + } - if((h + w) > 900) - { - sizefactor = (double)900/(h+w); - resize(I,I,Size(rounding(h*sizefactor),rounding(w*sizefactor))); - img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); - } - else - { - img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); - } + obj.init(); - obj.init(); + vector Cg; + vector < vector > polyGrad; + vector < vector > bc; + vector < vector < int > > comb; - vector Cg; - vector < vector > polyGrad; - vector < vector > bc; - vector < vector < int > > comb; + vector alf; - vector alf; + obj.grad_system(img,polyGrad,Cg,comb); + obj.weak_order(img,alf); + + Mat Mt = Mat(polyGrad.size(),polyGrad[0].size(), CV_32FC1); + obj.wei_update_matrix(polyGrad,Cg,Mt); + + vector wei; + obj.wei_inti(comb,wei); + + //////////////////////////////// main loop starting //////////////////////////////////////// + + while (iterCount < maxIter) + { + iterCount +=1; + + vector G_pos; + vector G_neg; + + vector temp; + vector temp1; + + double val = 0.0; + for(unsigned int i=0;i< polyGrad[0].size();i++) + { + val = 0.0; + for(unsigned int j =0;j EXPsum; + vector EXPterm; + + for(unsigned int i = 0;i temp2; + + for(unsigned int i=0;i wei1; + + for(unsigned int i=0;i< polyGrad.size();i++) + { + val1 = 0.0; + for(unsigned int j =0;j(i,j) * EXPterm[j]); + } + wei1.push_back(val1); + } + + for(unsigned int i =0;i product(vector < vector > &comb, vector &initRGB); + void singleChannelGradx(const Mat &img, Mat& dest); + void singleChannelGrady(const Mat &img, Mat& dest); + void gradvector(const Mat &img, vector &grad); + void colorGrad(Mat img, vector &Cg); + void add_vector(vector < vector > &comb, int r,int g,int b); + void add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad); + void weak_order(Mat img, vector &alf); void grad_system(Mat img, vector < vector < double > > &polyGrad, vector < double > &Cg, vector < vector >& comb); + void wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X); + void wei_inti(vector < vector > &comb, vector &wei); + void grayImContruct(vector &wei, Mat img, Mat &Gray); }; void Decolor::init() { - kernel = Mat(1,2, CV_32FC1); - kernel1 = Mat(2,1, CV_32FC1); - kernel.at(0,0)=1.0; - kernel.at(0,1)=-1.0; - kernel1.at(0,0)=1.0; - kernel1.at(1,0)=-1.0; - order = 2; + kernel = Mat(1,2, CV_32FC1); + kernel1 = Mat(2,1, CV_32FC1); + kernel.at(0,0)=1.0; + kernel.at(0,1)=-1.0; + kernel1.at(0,0)=1.0; + kernel1.at(1,0)=-1.0; + order = 2; } + +vector Decolor::product(vector < vector > &comb, vector &initRGB) +{ + vector res; + float dp; + for (unsigned int i=0;i(i,w-1)=0.0; +} + +void Decolor::singleChannelGrady(const Mat &img, Mat& dest) +{ + int w=img.size().width; + int h=img.size().height; + Point anchor(kernel1.cols - kernel1.cols/2 - 1, kernel1.rows - kernel1.rows/2 - 1); + filter2D(img, dest, -1, kernel1, anchor, 0.0, BORDER_CONSTANT); + for(int j=0;j(h-1,j)=0.0; +} + +void Decolor::gradvector(const Mat &img, vector &grad) +{ + Mat dest= Mat(img.size().height,img.size().width, CV_32FC1); + Mat dest1= Mat(img.size().height,img.size().width, CV_32FC1); + singleChannelGradx(img,dest); + singleChannelGrady(img,dest1); + + Mat d_trans=dest.t(); + Mat d1_trans=dest1.t(); + + int height = d_trans.size().height; + int width = d_trans.size().width; + + for(int i=0;i(i,j)); + + for(int i=0;i(i,j)); + dest.release(); + dest1.release(); +} + +void Decolor::colorGrad(Mat img, vector &Cg) +{ + + Mat lab = Mat(img.size(),CV_32FC3); + Mat l_channel = Mat(img.size(),CV_32FC1); + Mat a_channel = Mat(img.size(),CV_32FC1); + Mat b_channel = Mat(img.size(),CV_32FC1); + + cvtColor(img,lab,COLOR_BGR2Lab); + for(int i=0;i(i,j) = lab.at(i,j*3+0); + a_channel.at(i,j) = lab.at(i,j*3+1); + b_channel.at(i,j) = lab.at(i,j*3+2); + } + + vector ImL; + vector Ima; + vector Imb; + gradvector(l_channel,ImL); + gradvector(a_channel,Ima); + gradvector(b_channel,Imb); + + double res =0.0; + for(unsigned int i=0;i > &comb, int r,int g,int b) +{ + static int idx =0; + comb.push_back( vector () ); + comb.at(idx).push_back( r ); + comb.at(idx).push_back( g ); + comb.at(idx).push_back( b ); + idx++; +} + +void Decolor::add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad) +{ + static int idx1 =0; + polyGrad.push_back( vector () ); + for(unsigned int i=0;i &alf) +{ + Mat curIm = Mat(img.size(),CV_32FC1); + Mat red = Mat(img.size(),CV_32FC1); + Mat green = Mat(img.size(),CV_32FC1); + Mat blue = Mat(img.size(),CV_32FC1); + + for(int i=0;i(i,j) = img.at(i,j*3+2); + green.at(i,j) = img.at(i,j*3+1); + blue.at(i,j) = img.at(i,j*3+0); + } + + vector Rg; + vector Gg; + vector Bg; + + vector t1; + vector t2; + vector t3; + + vector tmp1; + vector tmp2; + vector tmp3; + + gradvector(red,Rg); + gradvector(green,Gg); + gradvector(blue,Bg); + double level = .05; + + for(unsigned int i=0;i level) + t1.push_back(1.0); + else + t1.push_back(0.0); + } + for(unsigned int i=0;i level) + t2.push_back(1.0); + else + t2.push_back(0.0); + } + for(unsigned int i=0;i level) + t3.push_back(1.0); + else + t3.push_back(0.0); + } + for(unsigned int i=0;i > &polyGrad, vector < double > &Cg, vector < vector >& comb) +{ + int h = img.size().height; + int w = img.size().width; + colorGrad(img,Cg); + + Mat curIm = Mat(img.size(),CV_32FC1); + Mat red = Mat(img.size(),CV_32FC1); + Mat green = Mat(img.size(),CV_32FC1); + Mat blue = Mat(img.size(),CV_32FC1); + + for(int i=0;i(i,j) = img.at(i,j*3+2); + green.at(i,j) = img.at(i,j*3+1); + blue.at(i,j) = img.at(i,j*3+0); + } + + for(int r=0 ;r <=order; r++) + for(int g=0; g<=order;g++) + for(int b =0; b <=order;b++) + { + if((r+g+b)<=order && (r+g+b) > 0) + { + add_vector(comb,r,g,b); + for(int i = 0;i(i,j)= + pow(red.at(i,j),r)*pow(green.at(i,j),g)* + pow(blue.at(i,j),b); + vector curGrad; + gradvector(curIm,curGrad); + add_to_vector_poly(polyGrad,curGrad); + } + } + + red.release(); + green.release(); + blue.release(); + curIm.release(); +} + +void Decolor::wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X) +{ + Mat P = Mat(poly.size(),poly[0].size(), CV_32FC1); + Mat A = Mat(poly.size(),poly.size(), CV_32FC1); + + for(unsigned int i =0;i(i,j) = poly[i][j]; + + Mat P_trans = P.t(); + Mat B = Mat(poly.size(),poly[0].size(), CV_32FC1); + for(unsigned int i =0;i < poly.size();i++) + { + for(unsigned int j=0;j(i,j) = poly[i][j]*Cg[j]; + } + + A = P*P_trans; + solve(A, B, X, DECOMP_NORMAL); + + P.release(); + A.release(); + B.release(); + +} + +void Decolor::wei_inti(vector < vector > &comb, vector &wei) +{ + vector initRGB; + + initRGB.push_back( .33 ); + initRGB.push_back( .33 ); + initRGB.push_back( .33 ); + wei = product(comb,initRGB); + + vector sum; + + for(unsigned int i=0;i &wei, Mat img, Mat &Gray) +{ + + int h=img.size().height; + int w=img.size().width; + + Mat red = Mat(img.size(),CV_32FC1); + Mat green = Mat(img.size(),CV_32FC1); + Mat blue = Mat(img.size(),CV_32FC1); + + for(int i=0;i(i,j) = img.at(i,j*3+2); + green.at(i,j) = img.at(i,j*3+1); + blue.at(i,j) = img.at(i,j*3+0); + } + + int kk =0; + + for(int r =0;r<=order;r++) + for(int g=0;g<=order;g++) + for(int b=0;b<=order;b++) + if((r + g + b) <=order && (r+g+b) > 0) + { + for(int i = 0;i(i,j)=Gray.at(i,j) + + wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* + pow(blue.at(i,j),b); + + kk=kk+1; + } + + double minval = INT_MAX; + double maxval = INT_MIN; + + for(int i=0;i(i,j) < minval) + minval = Gray.at(i,j); + + if(Gray.at(i,j) > maxval) + maxval = Gray.at(i,j); + } + + for(int i=0;i(i,j) = (Gray.at(i,j) - minval)/(maxval - minval); + + red.release(); + green.release(); + blue.release(); +} diff --git a/modules/photo/test/test_decolor.cpp b/modules/photo/test/test_decolor.cpp new file mode 100644 index 0000000000..3edec908a8 --- /dev/null +++ b/modules/photo/test/test_decolor.cpp @@ -0,0 +1,34 @@ +#include "test_precomp.hpp" +#include "opencv2/photo.hpp" +#include + +using namespace cv; +using namespace std; + +#ifdef DUMP_RESULTS +# define DUMP(image, path) imwrite(path, image) +#else +# define DUMP(image, path) +#endif + + +TEST(Photo_Decolor, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "decolor/"; + string original_path = folder + "color_image_1.png"; + string expected_path = folder + "grayscale_image_1.png"; + + Mat original = imread(original_path, IMREAD_COLOR); + Mat expected = imread(expected_path, IMREAD_GRAYSCALE); + + ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path; + ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path; + + Mat result; + decolor(original, result); + + DUMP(result, expected_path + ".res.png"); + + ASSERT_EQ(0, norm(result != expected)); +} + From a1b3ba02a702371d473d20545bce6d5a07afd9c6 Mon Sep 17 00:00:00 2001 From: siddharth Date: Mon, 1 Jul 2013 14:19:03 +0530 Subject: [PATCH 18/97] add color_boost + doc --- modules/photo/doc/decolor.rst | 20 +++++++++++ modules/photo/include/opencv2/photo.hpp | 2 +- modules/photo/src/contrast_preserve.cpp | 46 ++++++++++++++++++++++--- modules/photo/test/test_decolor.cpp | 19 ++++++---- 4 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 modules/photo/doc/decolor.rst diff --git a/modules/photo/doc/decolor.rst b/modules/photo/doc/decolor.rst new file mode 100644 index 0000000000..061b2b18c6 --- /dev/null +++ b/modules/photo/doc/decolor.rst @@ -0,0 +1,20 @@ +Decolorization +============== + +.. highlight:: cpp + +decolor +------- + +Transforms a color image to a grayscale image. It is a basic tool in digital printing, stylized black-and-white photograph rendering, and in many single channel image processing applications. + +.. ocv:function:: void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost ) + + :param src: Input 8-bit 3-channel image. + + :param grayscale: Output 8-bit 1-channel image. + + :param color_boost: Output 8-bit 3-channel image. + +This function is to be applied on color images. + diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 6f5868dd4c..e656b93e8a 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -288,7 +288,7 @@ public: CV_EXPORTS_W Ptr createMergeRobertson(); -CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale); +CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost); } // cv diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 6d4a2d1313..570ef8059f 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -17,14 +17,17 @@ int rounding(double a) return int(a + 0.5); } -void cv::decolor(InputArray _src, OutputArray _dst) +void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) { - Mat I = _src.getMat(); + Mat I = _src.getMat(); _dst.create(I.size(), CV_8UC1); Mat dst = _dst.getMat(); - if(!I.data ) - { + _boost.create(I.size(), CV_8UC3); + Mat color_boost = _boost.getMat(); + + if(!I.data ) + { cout << "Could not open or find the image" << endl ; return; } @@ -162,5 +165,40 @@ void cv::decolor(InputArray _src, OutputArray _dst) Gray.convertTo(dst,CV_8UC1,255); + /////////////////////////////////// Contrast Boosting ///////////////////////////////// + Mat lab = Mat(img.size(),CV_8UC3); + Mat color = Mat(img.size(),CV_8UC3); + Mat l = Mat(img.size(),CV_8UC1); + Mat a = Mat(img.size(),CV_8UC1); + Mat b = Mat(img.size(),CV_8UC1); + + cvtColor(I,lab,COLOR_BGR2Lab); + + int h1 = img.size().height; + int w1 = img.size().width; + + for(int i =0;i(i,j) = lab.at(i,j*3+0); + a.at(i,j) = lab.at(i,j*3+1); + b.at(i,j) = lab.at(i,j*3+2); + } + + for(int i =0;i(i,j) = 255.0*Gray.at(i,j); + } + + for(int i =0;i(i,j*3+0) = l.at(i,j); + lab.at(i,j*3+1) = a.at(i,j); + lab.at(i,j*3+2) = b.at(i,j); + } + + cvtColor(lab,color_boost,COLOR_Lab2BGR); } diff --git a/modules/photo/test/test_decolor.cpp b/modules/photo/test/test_decolor.cpp index 3edec908a8..94f78a7df0 100644 --- a/modules/photo/test/test_decolor.cpp +++ b/modules/photo/test/test_decolor.cpp @@ -16,19 +16,24 @@ TEST(Photo_Decolor, regression) { string folder = string(cvtest::TS::ptr()->get_data_path()) + "decolor/"; string original_path = folder + "color_image_1.png"; - string expected_path = folder + "grayscale_image_1.png"; + string expected_path1 = folder + "grayscale_image_1.png"; + string expected_path2 = folder + "color_boost_image_1.png"; Mat original = imread(original_path, IMREAD_COLOR); - Mat expected = imread(expected_path, IMREAD_GRAYSCALE); + Mat expected1 = imread(expected_path1, IMREAD_GRAYSCALE); + Mat expected2 = imread(expected_path2, IMREAD_COLOR); ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path; - ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path; + ASSERT_FALSE(expected1.empty()) << "Could not load reference image " << expected_path1; + ASSERT_FALSE(expected2.empty()) << "Could not load reference image " << expected_path2; - Mat result; - decolor(original, result); + Mat grayscale, color_boost; + decolor(original, grayscale, color_boost); - DUMP(result, expected_path + ".res.png"); + DUMP(grayscale, expected_path1 + ".grayscale.png"); + DUMP(color_boost, expected_path2 + ".color_boost.png"); - ASSERT_EQ(0, norm(result != expected)); + ASSERT_EQ(0, norm(grayscale != expected1)); + ASSERT_EQ(0, norm(color_boost != expected2)); } From 0802c06571e89b7ae66a7e008d5eb1f4115c7dd6 Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 12 Jul 2013 09:18:37 +0530 Subject: [PATCH 19/97] seamless cloning added update1 update1 update4 --- modules/photo/include/opencv2/photo.hpp | 21 + modules/photo/src/seamless_cloning.cpp | 374 +++++++++++ modules/photo/src/seamless_cloning.hpp | 836 ++++++++++++++++++++++++ 3 files changed, 1231 insertions(+) create mode 100644 modules/photo/src/seamless_cloning.cpp create mode 100644 modules/photo/src/seamless_cloning.hpp diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index e656b93e8a..fd05b4ca9b 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -59,6 +59,19 @@ enum INPAINT_TELEA = 1 // A. Telea algorithm }; +enum +{ + NORMAL_CLONE = 1, + MIXED_CLONE = 2, + FEATURE_EXCHANGE = 3 +}; + +enum +{ + FOREGROUND_COLOR_CHANGE = 4, + BACKGROUND_DECOLOR = 5 +}; + //! restores the damaged image areas using one of the available intpainting algorithms CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags ); @@ -290,6 +303,14 @@ CV_EXPORTS_W Ptr createMergeRobertson(); CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost); +CV_EXPORTS_W void seamlessClone(InputArray src, InputArray dst, OutputArray blend, int flags = 1); + +CV_EXPORTS_W void colorChange(InputArray src, OutputArray dst, int flags = 4, float red = 1.0, float green = 1.0, float blue = 1.0); + +CV_EXPORTS_W void illuminationChange(InputArray _src, OutputArray _dst, float alpha = 0.2, float beta = 0.4); + +CV_EXPORTS_W void textureFlattening(InputArray _src, OutputArray _dst); + } // cv #endif diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp new file mode 100644 index 0000000000..abb9636183 --- /dev/null +++ b/modules/photo/src/seamless_cloning.cpp @@ -0,0 +1,374 @@ +#include "precomp.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include + +#include "seamless_cloning.hpp" + +using namespace std; +using namespace cv; + +Mat img0, img1, img2, res, res1, final, final1, blend; + +Point point; +int drag = 0; +int destx, desty; + +int numpts = 100; +Point* pts = new Point[100]; +Point* pts1 = new Point[100]; +Point* pts2 = new Point[100]; + + +int var = 0; +int flag = 0; +int flag1 = 0; + +int minx,miny,maxx,maxy,lenx,leny; +int minxd,minyd,maxxd,maxyd,lenxd,lenyd; + +int channel,num; + +float alpha,beta; + +float red, green, blue; +void mouseHandler(int , int , int , int, void*); +void mouseHandler1(int , int , int , int, void*); +void mouseHandler(int event, int x, int y, int, void*) +{ + + if (event == EVENT_LBUTTONDOWN && !drag) + { + if(flag1 == 0) + { + if(var==0) + img1 = img0.clone(); + point = Point(x, y); + circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); + pts[var] = point; + var++; + drag = 1; + if(var>1) + line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); + + imshow("Source", img1); + } + } + + + if (event == EVENT_LBUTTONUP && drag) + { + imshow("Source", img1); + + drag = 0; + } + if (event == EVENT_RBUTTONDOWN) + { + flag1 = 1; + img1 = img0.clone(); + for(int i = var; i < numpts ; i++) + pts[i] = point; + + if(var!=0) + { + const Point* pts3[1] = {&pts[0]}; + polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); + } + + for(int i=0;i(i,j*3+0) = img3.at(i,j); + img4.at(i,j*3+1) = img3.at(i,j); + img4.at(i,j*3+2) = img3.at(i,j); + } + + obj.local_color_change(img4,final,res1,blend,num); + + namedWindow("Background Decolor Image"); + imshow("Background Decolor Image", blend); + waitKey(0); + } + else if(num == 6) + { + Cloning obj; + obj.illum_change(img0,final,res1,blend,alpha,beta); + + namedWindow("Illum Change Image"); + imshow("Illum Change Image", blend); + waitKey(0); + + } + + } + if (event == EVENT_MBUTTONDOWN) + { + for(int i = 0; i < numpts ; i++) + { + pts[i].x=0; + pts[i].y=0; + } + var = 0; + flag1 = 0; + minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + imshow("Source", img0); + drag = 0; + } +} + + +void mouseHandler1(int event, int x, int y, int, void*) +{ + + + Mat im1; + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + im1 = img2.clone(); + if (event == EVENT_LBUTTONDOWN) + { + if(flag1 == 1) + { + point = Point(x, y); + + for(int i =0; i < numpts;i++) + pts1[i] = pts[i]; + + int tempx; + int tempy; + for(int i =0; i < flag; i++) + { + tempx = pts1[i+1].x - pts1[i].x; + tempy = pts1[i+1].y - pts1[i].y; + if(i==0) + { + pts2[i+1].x = point.x + tempx; + pts2[i+1].y = point.y + tempy; + } + else if(i>0) + { + pts2[i+1].x = pts2[i].x + tempx; + pts2[i+1].y = pts2[i].y + tempy; + } + + } + + for(int i=flag;i im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0) + { + cout << "Index out of range" << endl; + exit(0); + } + + final1 = Mat::zeros(img2.size(),CV_8UC3); + res = Mat::zeros(img2.size(),CV_8UC1); + for(int i=miny, k=minyd;i<(miny+leny);i++,k++) + for(int j=minx,l=minxd ;j<(minx+lenx);j++,l++) + { + for(int c=0;c(k,l*channel+c) = final.at(i,j*channel+c); + + } + } + + + const Point* pts6[1] = {&pts2[0]}; + fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0); + + if(num == 1 || num == 2 || num == 3) + { + Cloning obj; + obj.normal_clone(img2,final1,res,blend,num); + namedWindow("Cloned Image"); + imshow("Cloned Image", blend); + waitKey(0); + } + + for(int i = 0; i < flag ; i++) + { + pts2[i].x=0; + pts2[i].y=0; + } + + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + } + + im1.release(); +} + +void cv::seamlessClone(InputArray _src, InputArray _dst, OutputArray _blend, int flags) +{ + Mat src = _src.getMat(); + Mat dest = _dst.getMat(); + _blend.create(dest.size(), CV_8UC3); + blend = _blend.getMat(); + + num = flags; + + minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + + img0 = src; + img2 = dest; + + channel = img0.channels(); + + res = Mat::zeros(img2.size(),CV_8UC1); + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + final1 = Mat::zeros(img2.size(),CV_8UC3); + //////////// source image /////////////////// + + namedWindow("Source", 1); + setMouseCallback("Source", mouseHandler, NULL); + imshow("Source", img0); + + /////////// destination image /////////////// + + namedWindow("Destination", 1); + setMouseCallback("Destination", mouseHandler1, NULL); + imshow("Destination",img2); + waitKey(0); + + img0.release(); + img1.release(); + img2.release(); +} + +void cv::colorChange(InputArray _src, OutputArray _dst, int flags, float r, float g, float b) +{ + Mat src = _src.getMat(); + _dst.create(src.size(), src.type()); + blend = _dst.getMat(); + + minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + + num = flags; + red = r; + green = g; + blue = b; + + img0 = src; + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + + namedWindow("Source"); + setMouseCallback("Source", mouseHandler, NULL); + imshow("Source", img0); + + waitKey(0); + + img0.release(); +} + + +void cv::illuminationChange(InputArray _src, OutputArray _dst, float a, float b) +{ + + Mat src = _src.getMat(); + _dst.create(src.size(), src.type()); + blend = _dst.getMat(); + num = 6; + alpha = a; + beta = b; + + img0 = src; + + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + + namedWindow("Source"); + setMouseCallback("Source", mouseHandler, NULL); + imshow("Source", img0); + + waitKey(0); +} +void cv::textureFlattening(InputArray _src, OutputArray _dst) +{ + + Mat src = _src.getMat(); + _dst.create(src.size(), src.type()); + blend = _dst.getMat(); + img0 = src; + + Cloning obj; + obj.texture_flatten(img0,blend); + + namedWindow("Texture Flattened Image"); + imshow("Texture Flattened Image", blend); + waitKey(0); + +} + diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp new file mode 100644 index 0000000000..acff7059b4 --- /dev/null +++ b/modules/photo/src/seamless_cloning.hpp @@ -0,0 +1,836 @@ +#include "precomp.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include +#include +#include "math.h" + +using namespace std; +using namespace cv; + +#define pi 3.1416 + +class Cloning +{ + + public: + + Mat grx,gry,sgx,sgy,r_channel,g_channel,b_channel,smask1,grx32,gry32; + Mat smask,srx32,sry32; + Mat rx_channel,ry_channel,gx_channel,gy_channel,bx_channel,by_channel,resultr,resultg,resultb; + void init(Mat &I, Mat &wmask); + void calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy); + void getGradientx(const Mat &img, Mat &gx); + void getGradienty(const Mat &img, Mat &gy); + void lapx(const Mat &img, Mat &gxx); + void lapy(const Mat &img, Mat &gyy); + void dst(double *gtest, double *gfinal,int h,int w); + void idst(double *gtest, double *gfinal,int h,int w); + void transpose(double *mat, double *mat_t,int h,int w); + void poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result); + void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num); + void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num, float red, float green, float blue); + void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta); + void texture_flatten(Mat &I, Mat &final); + }; + +void Cloning::getGradientx( const Mat &img, Mat &gx) +{ + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); + + gx = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i,j*channel+c) = + (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); + } +} +void Cloning::getGradienty( const Mat &img, Mat &gy) +{ + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); + + gy = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i,j*channel+c) = + (float)img.at((i+1),j*channel+c) - (float)img.at(i,j*channel+c); + + } +} +void Cloning::lapx( const Mat &img, Mat &gxx) +{ + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); + + gxx = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i,(j+1)*channel+c) = + (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); + } +} +void Cloning::lapy( const Mat &img, Mat &gyy) +{ + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); + gyy = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i+1,j*channel+c) = + (float)img.at((i+1),j*channel+c) - (float)img.at(i,j*channel+c); + + } +} + +void Cloning::dst(double *gtest, double *gfinal,int h,int w) +{ + + unsigned long int idx; + + Mat temp = Mat(2*h+2,1,CV_32F); + Mat res = Mat(h,1,CV_32F); + + Mat planes[] = {Mat_(temp), Mat::zeros(temp.size(), CV_32F)}; + + Mat complex1; + int p=0; + for(int i=0;i(0,0) = 0.0; + + for(int j=0,r=1;j(r,0) = gtest[idx]; + } + + temp.at(h+1,0)=0.0; + + for(int j=h-1, r=h+2;j>=0;j--,r++) + { + idx = j*w+i; + temp.at(r,0) = -1*gtest[idx]; + } + + merge(planes, 2, complex1); + + dft(complex1,complex1,0,0); + + Mat planes1[] = {Mat::zeros(complex1.size(), CV_32F), Mat::zeros(complex1.size(), CV_32F)}; + + split(complex1, planes1); + + std::complex two_i = std::sqrt(std::complex(-1)); + + double fac = -2*imag(two_i); + + for(int c=1,z=0;c(z,0) = planes1[1].at(c,0)/fac; + } + + for(int q=0,z=0;q(z,0); + } + p++; + } + + temp.release(); + res.release(); + planes[0].release(); + planes[1].release(); + +} + +void Cloning::idst(double *gtest, double *gfinal,int h,int w) +{ + int nn = h+1; + unsigned long int idx; + dst(gtest,gfinal,h,w); + for(int i= 0;i(i,j) = mat[idx]; + } + } + Mat tmp_t = tmp.t(); + + for(int i = 0;i < tmp_t.size().height; i++) + for(int j=0;j(i,j); + } + + tmp.release(); + +} +void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) +{ + + int w = img.size().width; + int h = img.size().height; + + unsigned long int idx,idx1; + + Mat lap = Mat(img.size(),CV_32FC1); + + for(int i =0;i(i,j)=gyy.at(i,j)+gxx.at(i,j); + + Mat bound = img.clone(); + + for(int i =1;i(i,j) = 0.0; + } + + double *f_bp = new double[h*w]; + + + for(int i =1;i(i,j) + (int)bound.at(i,(j+1)) + (int)bound.at(i,(j-1)) + + (int)bound.at(i-1,j) + (int)bound.at(i+1,j); + } + + + Mat diff = Mat(h,w,CV_32FC1); + for(int i =0;i(i,j) = (lap.at(i,j) - f_bp[idx]); + } + } + + lap.release(); + + double *gtest = new double[(h-2)*(w-2)]; + for(int i = 0 ; i < h-2;i++) + { + for(int j = 0 ; j < w-2; j++) + { + idx = i*(w-2) + j; + gtest[idx] = diff.at(i+1,j+1); + + } + } + + diff.release(); + ///////////////////////////////////////////////////// Find DST ///////////////////////////////////////////////////// + + double *gfinal = new double[(h-2)*(w-2)]; + double *gfinal_t = new double[(h-2)*(w-2)]; + double *denom = new double[(h-2)*(w-2)]; + double *f3 = new double[(h-2)*(w-2)]; + double *f3_t = new double[(h-2)*(w-2)]; + double *img_d = new double[(h)*(w)]; + + dst(gtest,gfinal,h-2,w-2); + + transpose(gfinal,gfinal_t,h-2,w-2); + + dst(gfinal_t,gfinal,w-2,h-2); + + transpose(gfinal,gfinal_t,w-2,h-2); + + int cy=1; + + for(int i = 0 ; i < w-2;i++,cy++) + { + for(int j = 0,cx = 1; j < h-2; j++,cx++) + { + idx = j*(w-2) + i; + denom[idx] = (float) 2*cos(pi*cy/( (double) (w-1))) - 2 + 2*cos(pi*cx/((double) (h-1))) - 2; + + } + } + + for(idx = 0 ; idx < (unsigned)(w-2)*(h-2) ;idx++) + { + gfinal_t[idx] = gfinal_t[idx]/denom[idx]; + } + + + idst(gfinal_t,f3,h-2,w-2); + + transpose(f3,f3_t,h-2,w-2); + + idst(f3_t,f3,w-2,h-2); + + transpose(f3,f3_t,w-2,h-2); + + for(int i = 0 ; i < h;i++) + { + for(int j = 0 ; j < w; j++) + { + idx = i*w + j; + img_d[idx] = (double)img.at(i,j); + } + } + for(int i = 1 ; i < h-1;i++) + { + for(int j = 1 ; j < w-1; j++) + { + idx = i*w + j; + img_d[idx] = 0.0; + } + } + for(int i = 1,id1=0 ; i < h-1;i++,id1++) + { + for(int j = 1,id2=0 ; j < w-1; j++,id2++) + { + idx = i*w + j; + idx1= id1*(w-2) + id2; + img_d[idx] = f3_t[idx1]; + } + } + + for(int i = 0 ; i < h;i++) + { + for(int j = 0 ; j < w; j++) + { + idx = i*w + j; + if(img_d[idx] < 0.0) + result.at(i,j) = 0; + else if(img_d[idx] > 255.0) + result.at(i,j) = 255.0; + else + result.at(i,j) = img_d[idx]; + } + } + + delete [] gfinal; + delete [] gfinal_t; + delete [] denom; + delete [] f3; + delete [] f3_t; + delete [] img_d; + delete [] gtest; + delete [] f_bp; + +} + +void Cloning::init(Mat &I, Mat &wmask) +{ + + grx = Mat(I.size(),CV_32FC3); + gry = Mat(I.size(),CV_32FC3); + sgx = Mat(I.size(),CV_32FC3); + sgy = Mat(I.size(),CV_32FC3); + + r_channel = Mat::zeros(I.size(),CV_8UC1); + g_channel = Mat::zeros(I.size(),CV_8UC1); + b_channel = Mat::zeros(I.size(),CV_8UC1); + + for(int i=0;i(i,j) = I.at(i,j*3+0); + g_channel.at(i,j) = I.at(i,j*3+1); + b_channel.at(i,j) = I.at(i,j*3+2); + } + + smask = Mat(wmask.size(),CV_32FC1); + srx32 = Mat(I.size(),CV_32FC3); + sry32 = Mat(I.size(),CV_32FC3); + smask1 = Mat(wmask.size(),CV_32FC1); + grx32 = Mat(I.size(),CV_32FC3); + gry32 = Mat(I.size(),CV_32FC3); +} + +void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) +{ + + int channel = I.channels(); + Mat fx = Mat(I.size(),CV_32FC3); + Mat fy = Mat(I.size(),CV_32FC3); + + for(int i=0;i < I.size().height; i++) + for(int j=0; j < I.size().width; j++) + for(int c=0;c(i,j*channel+c) = + (gx.at(i,j*channel+c)+sx.at(i,j*channel+c)); + fy.at(i,j*channel+c) = + (gy.at(i,j*channel+c)+sy.at(i,j*channel+c)); + } + + Mat gxx = Mat(I.size(),CV_32FC3); + Mat gyy = Mat(I.size(),CV_32FC3); + + lapx(fx,gxx); + lapy(fy,gyy); + + rx_channel = Mat(I.size(),CV_32FC1); + gx_channel = Mat(I.size(),CV_32FC1); + bx_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gxx.at(i,j*3+0); + gx_channel.at(i,j) = gxx.at(i,j*3+1); + bx_channel.at(i,j) = gxx.at(i,j*3+2); + } + + ry_channel = Mat(I.size(),CV_32FC1); + gy_channel = Mat(I.size(),CV_32FC1); + by_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gyy.at(i,j*3+0); + gy_channel.at(i,j) = gyy.at(i,j*3+1); + by_channel.at(i,j) = gyy.at(i,j*3+2); + } + + resultr = Mat(I.size(),CV_8UC1); + resultg = Mat(I.size(),CV_8UC1); + resultb = Mat(I.size(),CV_8UC1); + + clock_t tic = clock(); + + + poisson_solver(r_channel,rx_channel, ry_channel,resultr); + poisson_solver(g_channel,gx_channel, gy_channel,resultg); + poisson_solver(b_channel,bx_channel, by_channel,resultb); + + clock_t toc = clock(); + + printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); + + +} +void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num) +{ + init(I,wmask); + + int w = I.size().width; + int h = I.size().height; + int channel = I.channels(); + + getGradientx(I,grx); + getGradienty(I,gry); + + if(num != 3) + { + getGradientx(mask,sgx); + getGradienty(mask,sgy); + } + + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); + + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); + + if(num == 1) + { + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + + } + else if(num == 2) + { + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) - sgy.at(i,j*channel+c)) > + abs(grx.at(i,j*channel+c) - gry.at(i,j*channel+c))) + { + + srx32.at(i,j*channel+c) = sgx.at(i,j*channel+c) + * smask.at(i,j); + sry32.at(i,j*channel+c) = sgy.at(i,j*channel+c) + * smask.at(i,j); + } + else + { + srx32.at(i,j*channel+c) = grx.at(i,j*channel+c) + * smask.at(i,j); + sry32.at(i,j*channel+c) = gry.at(i,j*channel+c) + * smask.at(i,j); + } + } + } + else if(num == 3) + { + Mat gray = Mat(mask.size(),CV_8UC1); + Mat gray8 = Mat(mask.size(),CV_8UC3); + cvtColor(mask, gray, COLOR_BGR2GRAY ); + + for(int i=0;i(i,j*3+0) = gray.at(i,j); + gray8.at(i,j*3+1) = gray.at(i,j); + gray8.at(i,j*3+2) = gray.at(i,j); + } + + + getGradientx(gray8,sgx); + getGradienty(gray8,sgy); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + + } + + bitwise_not(wmask,wmask); + + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } + + calc(I,grx32,gry32,srx32,sry32); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } + +} + +void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num, float red=1.0, float green=1.0, float blue=1.0) +{ + init(I,wmask); + + int w = I.size().width; + int h = I.size().height; + int channel = I.channels(); + + getGradientx(I,grx); + getGradienty(I,gry); + + getGradientx(mask,sgx); + getGradienty(mask,sgy); + + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); + + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + + if(num == 4) + { + Mat factor = Mat(I.size(),CV_32FC3); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + { + factor.at(i,j*channel+0) = blue; + factor.at(i,j*channel+1) = green; + factor.at(i,j*channel+2) = red; + } + + + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + srx32.at(i,j*channel+c)*factor.at(i,j*channel+c); + sry32.at(i,j*channel+c) = + sry32.at(i,j*channel+c)*factor.at(i,j*channel+c); + } + } + + bitwise_not(wmask,wmask); + + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } + + calc(I,grx32,gry32,srx32,sry32); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } + +} + +void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta) +{ + init(I,wmask); + + int w = I.size().width; + int h = I.size().height; + int channel = I.channels(); + + getGradientx(I,grx); + getGradienty(I,gry); + + getGradientx(mask,sgx); + getGradienty(mask,sgy); + + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); + + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + + + Mat mag = Mat(I.size(),CV_32FC3); + I.convertTo(mag,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + sqrt(pow(srx32.at(i,j*channel+c),2) + pow(sry32.at(i,j*channel+c),2)); + } + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) != 0) + { + srx32.at(i,j*channel+c) = + pow(alpha,beta)*srx32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); + sry32.at(i,j*channel+c) = + pow(alpha,beta)*sry32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); + } + } + + bitwise_not(wmask,wmask); + + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } + + calc(I,grx32,gry32,srx32,sry32); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } +} + +void Cloning::texture_flatten(Mat &I, Mat &final) +{ + + grx = Mat(I.size(),CV_32FC3); + gry = Mat(I.size(),CV_32FC3); + + Mat out = Mat(I.size(),CV_8UC1); + + getGradientx( I, grx); + getGradienty( I, gry); + + Canny( I, out, 30, 45, 3 ); + + int channel = I.channels(); + + for(int i=0;i(i,j) != 255) + { + grx.at(i,j*channel+c) = 0.0; + gry.at(i,j*channel+c) = 0.0; + } + } + + r_channel = Mat::zeros(I.size(),CV_8UC1); + g_channel = Mat::zeros(I.size(),CV_8UC1); + b_channel = Mat::zeros(I.size(),CV_8UC1); + + for(int i=0;i(i,j) = I.at(i,j*3+0); + g_channel.at(i,j) = I.at(i,j*3+1); + b_channel.at(i,j) = I.at(i,j*3+2); + } + + Mat gxx = Mat(I.size(),CV_32FC3); + Mat gyy = Mat(I.size(),CV_32FC3); + + lapx(grx,gxx); + lapy(gry,gyy); + + rx_channel = Mat(I.size(),CV_32FC1); + gx_channel = Mat(I.size(),CV_32FC1); + bx_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gxx.at(i,j*3+0); + gx_channel.at(i,j) = gxx.at(i,j*3+1); + bx_channel.at(i,j) = gxx.at(i,j*3+2); + } + + ry_channel = Mat(I.size(),CV_32FC1); + gy_channel = Mat(I.size(),CV_32FC1); + by_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gyy.at(i,j*3+0); + gy_channel.at(i,j) = gyy.at(i,j*3+1); + by_channel.at(i,j) = gyy.at(i,j*3+2); + } + + resultr = Mat(I.size(),CV_8UC1); + resultg = Mat(I.size(),CV_8UC1); + resultb = Mat(I.size(),CV_8UC1); + + clock_t tic = clock(); + + + poisson_solver(r_channel,rx_channel, ry_channel,resultr); + poisson_solver(g_channel,gx_channel, gy_channel,resultg); + poisson_solver(b_channel,bx_channel, by_channel,resultb); + + clock_t toc = clock(); + + printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } +} From 5b0ee9e08580efceda96ce4595ea7488450f909e Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 26 Jul 2013 11:33:27 +0530 Subject: [PATCH 20/97] decolor module updated --- modules/photo/src/contrast_preserve.cpp | 42 +- modules/photo/src/contrast_preserve.hpp | 685 +++++++++++++----------- 2 files changed, 391 insertions(+), 336 deletions(-) diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 570ef8059f..154f997d8b 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -1,6 +1,7 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" +#include #include "math.h" #include #include @@ -10,11 +11,11 @@ using namespace std; using namespace cv; -int rounding(double a); +double norm(double); -int rounding(double a) +double norm(double E) { - return int(a + 0.5); + return (sqrt(pow(E,2))); } void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) @@ -37,33 +38,20 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) return; } - float sigma = .02; - int maxIter = 8; + int maxIter = 15; int iterCount = 0; - - int h = I.size().height; - int w = I.size().width; + float tol = .0001; + double E = 0; + double pre_E = std::numeric_limits::infinity(); Decolor obj; Mat img; - - double sizefactor; - if((h + w) > 900) - { - sizefactor = (double)900/(h+w); - resize(I,I,Size(rounding(h*sizefactor),rounding(w*sizefactor))); - img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); - } - else - { - img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); - } + img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); - obj.init(); + obj.init(); vector Cg; vector < vector > polyGrad; @@ -83,9 +71,10 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) //////////////////////////////// main loop starting //////////////////////////////////////// - while (iterCount < maxIter) + while(norm(E-pre_E) > tol) { iterCount +=1; + pre_E = E; vector G_pos; vector G_neg; @@ -150,6 +139,11 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) for(unsigned int i =0;i maxIter) + break; + G_pos.clear(); G_neg.clear(); temp.clear(); diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 440427fa28..77fc2195ce 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -10,411 +10,472 @@ using namespace cv; class Decolor { - private: - Mat kernel; - Mat kernel1; - int order; - - public: - void init(); - vector product(vector < vector > &comb, vector &initRGB); - void singleChannelGradx(const Mat &img, Mat& dest); - void singleChannelGrady(const Mat &img, Mat& dest); - void gradvector(const Mat &img, vector &grad); - void colorGrad(Mat img, vector &Cg); - void add_vector(vector < vector > &comb, int r,int g,int b); - void add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad); - void weak_order(Mat img, vector &alf); - void grad_system(Mat img, vector < vector < double > > &polyGrad, vector < double > &Cg, vector < vector >& comb); - void wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X); - void wei_inti(vector < vector > &comb, vector &wei); - void grayImContruct(vector &wei, Mat img, Mat &Gray); + private: + Mat kernel; + Mat kernel1; + int order; + + public: + void init(); + vector product(vector < vector > &comb, vector &initRGB); + double energyCalcu(vector &Cg, vector < vector > &polyGrad, vector &wei); + void singleChannelGradx(const Mat &img, Mat& dest); + void singleChannelGrady(const Mat &img, Mat& dest); + void gradvector(const Mat &img, vector &grad); + void colorGrad(Mat img, vector &Cg); + void add_vector(vector < vector > &comb, int r,int g,int b); + void add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad); + void weak_order(Mat img, vector &alf); + void grad_system(Mat img, vector < vector < double > > &polyGrad, + vector < double > &Cg, vector < vector >& comb); + void wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X); + void wei_inti(vector < vector > &comb, vector &wei); + void grayImContruct(vector &wei, Mat img, Mat &Gray); }; +int rounding(double a); + +int rounding(double a) +{ + return int(a + 0.5); +} + +float sigma = .02; + +double Decolor::energyCalcu(vector &Cg, vector < vector > &polyGrad, vector &wei) +{ + vector P; + + vector temp; + vector temp1; + + double val = 0.0; + for(unsigned int i=0;i< polyGrad[0].size();i++) + { + val = 0.0; + for(unsigned int j =0;j(0,0)=1.0; - kernel.at(0,1)=-1.0; - kernel1.at(0,0)=1.0; - kernel1.at(1,0)=-1.0; - order = 2; + kernel = Mat(1,2, CV_32FC1); + kernel1 = Mat(2,1, CV_32FC1); + kernel.at(0,0)=1.0; + kernel.at(0,1)=-1.0; + kernel1.at(0,0)=1.0; + kernel1.at(1,0)=-1.0; + order = 2; } vector Decolor::product(vector < vector > &comb, vector &initRGB) { - vector res; - float dp; - for (unsigned int i=0;i res; + float dp; + for (unsigned int i=0;i(i,w-1)=0.0; + int w=img.size().width; + int h=img.size().height; + Point anchor(kernel.cols - kernel.cols/2 - 1, kernel.rows - kernel.rows/2 - 1); + filter2D(img, dest, -1, kernel, anchor, 0.0, BORDER_CONSTANT); + for(int i=0;i(i,w-1)=0.0; } void Decolor::singleChannelGrady(const Mat &img, Mat& dest) { - int w=img.size().width; - int h=img.size().height; - Point anchor(kernel1.cols - kernel1.cols/2 - 1, kernel1.rows - kernel1.rows/2 - 1); - filter2D(img, dest, -1, kernel1, anchor, 0.0, BORDER_CONSTANT); - for(int j=0;j(h-1,j)=0.0; + int w=img.size().width; + int h=img.size().height; + Point anchor(kernel1.cols - kernel1.cols/2 - 1, kernel1.rows - kernel1.rows/2 - 1); + filter2D(img, dest, -1, kernel1, anchor, 0.0, BORDER_CONSTANT); + for(int j=0;j(h-1,j)=0.0; } void Decolor::gradvector(const Mat &img, vector &grad) { - Mat dest= Mat(img.size().height,img.size().width, CV_32FC1); - Mat dest1= Mat(img.size().height,img.size().width, CV_32FC1); - singleChannelGradx(img,dest); - singleChannelGrady(img,dest1); + Mat dest= Mat(img.size().height,img.size().width, CV_32FC1); + Mat dest1= Mat(img.size().height,img.size().width, CV_32FC1); + singleChannelGradx(img,dest); + singleChannelGrady(img,dest1); - Mat d_trans=dest.t(); - Mat d1_trans=dest1.t(); + Mat d_trans=dest.t(); + Mat d1_trans=dest1.t(); - int height = d_trans.size().height; - int width = d_trans.size().width; + int height = d_trans.size().height; + int width = d_trans.size().width; - for(int i=0;i(i,j)); + for(int i=0;i(i,j)); - for(int i=0;i(i,j)); - dest.release(); - dest1.release(); + for(int i=0;i(i,j)); + dest.release(); + dest1.release(); } - + void Decolor::colorGrad(Mat img, vector &Cg) { - Mat lab = Mat(img.size(),CV_32FC3); - Mat l_channel = Mat(img.size(),CV_32FC1); - Mat a_channel = Mat(img.size(),CV_32FC1); - Mat b_channel = Mat(img.size(),CV_32FC1); + Mat lab = Mat(img.size(),CV_32FC3); + Mat l_channel = Mat(img.size(),CV_32FC1); + Mat a_channel = Mat(img.size(),CV_32FC1); + Mat b_channel = Mat(img.size(),CV_32FC1); - cvtColor(img,lab,COLOR_BGR2Lab); - for(int i=0;i(i,j) = lab.at(i,j*3+0); - a_channel.at(i,j) = lab.at(i,j*3+1); - b_channel.at(i,j) = lab.at(i,j*3+2); - } + cvtColor(img,lab,COLOR_BGR2Lab); + for(int i=0;i(i,j) = lab.at(i,j*3+0); + a_channel.at(i,j) = lab.at(i,j*3+1); + b_channel.at(i,j) = lab.at(i,j*3+2); + } - vector ImL; - vector Ima; - vector Imb; - gradvector(l_channel,ImL); - gradvector(a_channel,Ima); - gradvector(b_channel,Imb); + vector ImL; + vector Ima; + vector Imb; + gradvector(l_channel,ImL); + gradvector(a_channel,Ima); + gradvector(b_channel,Imb); - double res =0.0; - for(unsigned int i=0;i > &comb, int r,int g,int b) { - static int idx =0; - comb.push_back( vector () ); - comb.at(idx).push_back( r ); - comb.at(idx).push_back( g ); - comb.at(idx).push_back( b ); - idx++; + static int idx =0; + comb.push_back( vector () ); + comb.at(idx).push_back( r ); + comb.at(idx).push_back( g ); + comb.at(idx).push_back( b ); + idx++; } void Decolor::add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad) { - static int idx1 =0; - polyGrad.push_back( vector () ); - for(unsigned int i=0;i() ); + for(unsigned int i=0;i &alf) { - Mat curIm = Mat(img.size(),CV_32FC1); - Mat red = Mat(img.size(),CV_32FC1); - Mat green = Mat(img.size(),CV_32FC1); - Mat blue = Mat(img.size(),CV_32FC1); + int h = img.size().height; + int w = img.size().width; + double sizefactor; + if((h + w) > 800) + { + sizefactor = (double)800/(h+w); + resize(img,img,Size(rounding(h*sizefactor),rounding(w*sizefactor))); + } - for(int i=0;i(i,j) = img.at(i,j*3+2); - green.at(i,j) = img.at(i,j*3+1); - blue.at(i,j) = img.at(i,j*3+0); - } - - vector Rg; - vector Gg; - vector Bg; + Mat curIm = Mat(img.size(),CV_32FC1); + Mat red = Mat(img.size(),CV_32FC1); + Mat green = Mat(img.size(),CV_32FC1); + Mat blue = Mat(img.size(),CV_32FC1); - vector t1; - vector t2; - vector t3; - - vector tmp1; - vector tmp2; - vector tmp3; + for(int i=0;i(i,j) = img.at(i,j*3+2); + green.at(i,j) = img.at(i,j*3+1); + blue.at(i,j) = img.at(i,j*3+0); + } + + vector Rg; + vector Gg; + vector Bg; - gradvector(red,Rg); - gradvector(green,Gg); - gradvector(blue,Bg); - double level = .05; + vector t1; + vector t2; + vector t3; + + vector tmp1; + vector tmp2; + vector tmp3; - for(unsigned int i=0;i level) - t1.push_back(1.0); - else - t1.push_back(0.0); - } - for(unsigned int i=0;i level) - t2.push_back(1.0); - else - t2.push_back(0.0); - } - for(unsigned int i=0;i level) - t3.push_back(1.0); - else - t3.push_back(0.0); - } - for(unsigned int i=0;i level) + t1.push_back(1.0); + else + t1.push_back(0.0); + } + for(unsigned int i=0;i level) + t2.push_back(1.0); + else + t2.push_back(0.0); + } + for(unsigned int i=0;i level) + t3.push_back(1.0); + else + t3.push_back(0.0); + } + for(unsigned int i=0;i > &polyGrad, vector < double > &Cg, vector < vector >& comb) +void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, + vector < double > &Cg, vector < vector >& comb) { - int h = img.size().height; - int w = img.size().width; - colorGrad(img,Cg); - - Mat curIm = Mat(img.size(),CV_32FC1); - Mat red = Mat(img.size(),CV_32FC1); - Mat green = Mat(img.size(),CV_32FC1); - Mat blue = Mat(img.size(),CV_32FC1); + int h = img.size().height; + int w = img.size().width; - for(int i=0;i(i,j) = img.at(i,j*3+2); - green.at(i,j) = img.at(i,j*3+1); - blue.at(i,j) = img.at(i,j*3+0); - } - for(int r=0 ;r <=order; r++) - for(int g=0; g<=order;g++) - for(int b =0; b <=order;b++) - { - if((r+g+b)<=order && (r+g+b) > 0) - { - add_vector(comb,r,g,b); - for(int i = 0;i(i,j)= - pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); - vector curGrad; - gradvector(curIm,curGrad); - add_to_vector_poly(polyGrad,curGrad); - } - } + double sizefactor; + if((h + w) > 800) + { + sizefactor = (double)800/(h+w); + resize(img,img,Size(rounding(h*sizefactor),rounding(w*sizefactor))); + } - red.release(); - green.release(); - blue.release(); - curIm.release(); + h = img.size().height; + w = img.size().width; + colorGrad(img,Cg); + + Mat curIm = Mat(img.size(),CV_32FC1); + Mat red = Mat(img.size(),CV_32FC1); + Mat green = Mat(img.size(),CV_32FC1); + Mat blue = Mat(img.size(),CV_32FC1); + + for(int i=0;i(i,j) = img.at(i,j*3+2); + green.at(i,j) = img.at(i,j*3+1); + blue.at(i,j) = img.at(i,j*3+0); + } + + for(int r=0 ;r <=order; r++) + for(int g=0; g<=order;g++) + for(int b =0; b <=order;b++) + { + if((r+g+b)<=order && (r+g+b) > 0) + { + add_vector(comb,r,g,b); + for(int i = 0;i(i,j)= + pow(red.at(i,j),r)*pow(green.at(i,j),g)* + pow(blue.at(i,j),b); + vector curGrad; + gradvector(curIm,curGrad); + add_to_vector_poly(polyGrad,curGrad); + } + } + + red.release(); + green.release(); + blue.release(); + curIm.release(); } void Decolor::wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X) { - Mat P = Mat(poly.size(),poly[0].size(), CV_32FC1); - Mat A = Mat(poly.size(),poly.size(), CV_32FC1); + Mat P = Mat(poly.size(),poly[0].size(), CV_32FC1); + Mat A = Mat(poly.size(),poly.size(), CV_32FC1); - for(unsigned int i =0;i(i,j) = poly[i][j]; + for(unsigned int i =0;i(i,j) = poly[i][j]; - Mat P_trans = P.t(); - Mat B = Mat(poly.size(),poly[0].size(), CV_32FC1); - for(unsigned int i =0;i < poly.size();i++) - { - for(unsigned int j=0;j(i,j) = poly[i][j]*Cg[j]; - } + Mat P_trans = P.t(); + Mat B = Mat(poly.size(),poly[0].size(), CV_32FC1); + for(unsigned int i =0;i < poly.size();i++) + { + for(unsigned int j=0;j(i,j) = poly[i][j]*Cg[j]; + } - A = P*P_trans; - solve(A, B, X, DECOMP_NORMAL); + A = P*P_trans; + solve(A, B, X, DECOMP_NORMAL); - P.release(); - A.release(); - B.release(); + P.release(); + A.release(); + B.release(); } void Decolor::wei_inti(vector < vector > &comb, vector &wei) { - vector initRGB; + vector initRGB; - initRGB.push_back( .33 ); - initRGB.push_back( .33 ); - initRGB.push_back( .33 ); - wei = product(comb,initRGB); + initRGB.push_back( .33 ); + initRGB.push_back( .33 ); + initRGB.push_back( .33 ); + wei = product(comb,initRGB); - vector sum; + vector sum; - for(unsigned int i=0;i &wei, Mat img, Mat &Gray) { - int h=img.size().height; - int w=img.size().width; + int h=img.size().height; + int w=img.size().width; - Mat red = Mat(img.size(),CV_32FC1); - Mat green = Mat(img.size(),CV_32FC1); - Mat blue = Mat(img.size(),CV_32FC1); + Mat red = Mat(img.size(),CV_32FC1); + Mat green = Mat(img.size(),CV_32FC1); + Mat blue = Mat(img.size(),CV_32FC1); - for(int i=0;i(i,j) = img.at(i,j*3+2); - green.at(i,j) = img.at(i,j*3+1); - blue.at(i,j) = img.at(i,j*3+0); - } + for(int i=0;i(i,j) = img.at(i,j*3+2); + green.at(i,j) = img.at(i,j*3+1); + blue.at(i,j) = img.at(i,j*3+0); + } - int kk =0; - - for(int r =0;r<=order;r++) - for(int g=0;g<=order;g++) - for(int b=0;b<=order;b++) - if((r + g + b) <=order && (r+g+b) > 0) - { - for(int i = 0;i(i,j)=Gray.at(i,j) + - wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); + int kk =0; + + for(int r =0;r<=order;r++) + for(int g=0;g<=order;g++) + for(int b=0;b<=order;b++) + if((r + g + b) <=order && (r+g+b) > 0) + { + for(int i = 0;i(i,j)=Gray.at(i,j) + + wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* + pow(blue.at(i,j),b); - kk=kk+1; - } + kk=kk+1; + } - double minval = INT_MAX; - double maxval = INT_MIN; + double minval = INT_MAX; + double maxval = INT_MIN; - for(int i=0;i(i,j) < minval) - minval = Gray.at(i,j); - - if(Gray.at(i,j) > maxval) - maxval = Gray.at(i,j); - } + for(int i=0;i(i,j) < minval) + minval = Gray.at(i,j); + + if(Gray.at(i,j) > maxval) + maxval = Gray.at(i,j); + } - for(int i=0;i(i,j) = (Gray.at(i,j) - minval)/(maxval - minval); + for(int i=0;i(i,j) = (Gray.at(i,j) - minval)/(maxval - minval); - red.release(); - green.release(); - blue.release(); + red.release(); + green.release(); + blue.release(); } From e170115ad0d97f76879443184796ca8a23ac7522 Mon Sep 17 00:00:00 2001 From: siddharth Date: Mon, 5 Aug 2013 12:12:28 +0530 Subject: [PATCH 21/97] new interface added. decolor and cloning module added. Both modules added --- modules/photo/doc/cloning.rst | 88 ++ modules/photo/include/opencv2/photo.hpp | 14 +- modules/photo/src/contrast_preserve.cpp | 42 + modules/photo/src/contrast_preserve.hpp | 42 + modules/photo/src/seamless_cloning.cpp | 469 +++----- modules/photo/src/seamless_cloning.hpp | 1341 ++++++++++++----------- modules/photo/test/test_cloning.cpp | 179 +++ modules/photo/test/test_decolor.cpp | 61 +- samples/cpp/cloning.cpp | 288 +++++ samples/cpp/create_mask.cpp | 145 +++ 10 files changed, 1677 insertions(+), 992 deletions(-) create mode 100644 modules/photo/doc/cloning.rst create mode 100644 modules/photo/test/test_cloning.cpp create mode 100644 samples/cpp/cloning.cpp create mode 100644 samples/cpp/create_mask.cpp diff --git a/modules/photo/doc/cloning.rst b/modules/photo/doc/cloning.rst new file mode 100644 index 0000000000..740e1ab64b --- /dev/null +++ b/modules/photo/doc/cloning.rst @@ -0,0 +1,88 @@ +Seamless Cloning +================ + +.. highlight:: cpp + +seamlessClone +------------- +Image editing tasks concern either global changes (color/intensity corrections, filters, deformations) or local changes concerned to a selection. +Here we are interested in achieving local changes, ones that are restricted to a region manually selected (ROI), in a seamless and effortless manner. +The extent of the changes ranges from slight distortions to complete replacement by novel content. + +.. ocv:function:: void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, OutputArray result, int flags) + + :param src: Input 8-bit 3-channel image. + + :param dst: Input 8-bit 3-channel image. + + :param mask: Input 8-bit 1 or 3-channel image. + + :param Point: Point in dst image where object is placed. + + :param result: Output image with the same size and type as ``dst``. + + :param flags: Cloning method that could be one of the following: + + * **NORMAL_CLONE** The power of the method is fully expressed when inserting objects with complex outlines into a new background + + * **MIXED_CLONE** The classic method, color-based selection and alpha + masking might be time consuming and often leaves an undesirable halo. Seamless + cloning, even averaged with the original image, is not effective. Mixed seamless + cloning based on a loose selection proves effective. + + * **FEATURE_EXCHANGE** Feature exchange allows the user to replace easily certain + features of one object by alternative features. + + + +colorChange +----------- +Given an original color image, two differently colored versions of this image can be mixed seamlessly. + +.. ocv:function:: void colorChange( InputArray src, OutputArray dst, float red = 1.0, float green = 1.0, float blue = 1.0) + + :param src: Input 8-bit 3-channel image. + + :param dst: Output image with the same size and type as ``src`` . + + :param red: R-channel Value + + :param green: G-channel Value + + :param blue: B-channel Value + +RGB values between .5 to 2.5 + + +illuminationChange +------------------ +Applying an appropriate non-linear transformation to the gradient field inside the selection and then integrating back with a Poisson +solver, modifies locally the apparent illumination of an image. + +.. ocv:function:: void illuminationChange(InputArray src, OutputArray dst, float alpha = 0.2, float beta = 0.4) + + :param src: Input 8-bit 3-channel image. + + :param dst: Output image with the same size and type as ``src``. + + :param alpha: Value ranges between 0-2. + + :param beta: Value ranges between 0-2. + +This is useful to highlight under-exposed foreground objects or to reduce specular reflections. + +textureFlattening +----------------- +By retaining only the gradients at edge locations, before integrating with the Poisson solver, one washes out the texture of the selected +region, giving its contents a flat aspect. + +.. ocv:function:: void textureFlattening(InputArray src, OutputArray dst) + + :param src: Input 8-bit 3-channel image. + + :param dst: Output image with the same size and type as ``src``. + + +**NOTE:** + +The algorithm assumes that the color of the source image is close to that of the destination. This assumption means that when the colors don't match, the source image color gets tinted toward the color of the destination image. diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index fd05b4ca9b..673670354f 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -66,12 +66,6 @@ enum FEATURE_EXCHANGE = 3 }; -enum -{ - FOREGROUND_COLOR_CHANGE = 4, - BACKGROUND_DECOLOR = 5 -}; - //! restores the damaged image areas using one of the available intpainting algorithms CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags ); @@ -303,13 +297,13 @@ CV_EXPORTS_W Ptr createMergeRobertson(); CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost); -CV_EXPORTS_W void seamlessClone(InputArray src, InputArray dst, OutputArray blend, int flags = 1); +CV_EXPORTS_W void seamlessClone(InputArray src, InputArray dst, InputArray mask, Point p, OutputArray _blend, int flags); -CV_EXPORTS_W void colorChange(InputArray src, OutputArray dst, int flags = 4, float red = 1.0, float green = 1.0, float blue = 1.0); +CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red = 1.0, float green = 1.0, float blue = 1.0); -CV_EXPORTS_W void illuminationChange(InputArray _src, OutputArray _dst, float alpha = 0.2, float beta = 0.4); +CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, float alpha = 0.2, float beta = 0.4); -CV_EXPORTS_W void textureFlattening(InputArray _src, OutputArray _dst); +CV_EXPORTS_W void textureFlattening(InputArray src, OutputArray dst); } // cv diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 154f997d8b..9a659691a8 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -1,3 +1,45 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 77fc2195ce..607b494832 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -1,3 +1,45 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp index abb9636183..c2d6c59b97 100644 --- a/modules/photo/src/seamless_cloning.cpp +++ b/modules/photo/src/seamless_cloning.cpp @@ -1,3 +1,45 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" @@ -11,364 +53,161 @@ using namespace std; using namespace cv; -Mat img0, img1, img2, res, res1, final, final1, blend; - -Point point; -int drag = 0; -int destx, desty; - -int numpts = 100; -Point* pts = new Point[100]; -Point* pts1 = new Point[100]; -Point* pts2 = new Point[100]; - - -int var = 0; -int flag = 0; -int flag1 = 0; - -int minx,miny,maxx,maxy,lenx,leny; -int minxd,minyd,maxxd,maxyd,lenxd,lenyd; - -int channel,num; - -float alpha,beta; - -float red, green, blue; -void mouseHandler(int , int , int , int, void*); -void mouseHandler1(int , int , int , int, void*); -void mouseHandler(int event, int x, int y, int, void*) -{ - - if (event == EVENT_LBUTTONDOWN && !drag) - { - if(flag1 == 0) - { - if(var==0) - img1 = img0.clone(); - point = Point(x, y); - circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); - pts[var] = point; - var++; - drag = 1; - if(var>1) - line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); - - imshow("Source", img1); - } - } - - - if (event == EVENT_LBUTTONUP && drag) - { - imshow("Source", img1); - - drag = 0; - } - if (event == EVENT_RBUTTONDOWN) - { - flag1 = 1; - img1 = img0.clone(); - for(int i = var; i < numpts ; i++) - pts[i] = point; - - if(var!=0) - { - const Point* pts3[1] = {&pts[0]}; - polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); - } - - for(int i=0;i(i,j*3+0) = img3.at(i,j); - img4.at(i,j*3+1) = img3.at(i,j); - img4.at(i,j*3+2) = img3.at(i,j); - } - - obj.local_color_change(img4,final,res1,blend,num); - - namedWindow("Background Decolor Image"); - imshow("Background Decolor Image", blend); - waitKey(0); - } - else if(num == 6) - { - Cloning obj; - obj.illum_change(img0,final,res1,blend,alpha,beta); - - namedWindow("Illum Change Image"); - imshow("Illum Change Image", blend); - waitKey(0); - - } - - } - if (event == EVENT_MBUTTONDOWN) - { - for(int i = 0; i < numpts ; i++) - { - pts[i].x=0; - pts[i].y=0; - } - var = 0; - flag1 = 0; - minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; - imshow("Source", img0); - drag = 0; - } -} - - -void mouseHandler1(int event, int x, int y, int, void*) -{ - - - Mat im1; - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; - im1 = img2.clone(); - if (event == EVENT_LBUTTONDOWN) - { - if(flag1 == 1) - { - point = Point(x, y); - - for(int i =0; i < numpts;i++) - pts1[i] = pts[i]; - - int tempx; - int tempy; - for(int i =0; i < flag; i++) - { - tempx = pts1[i+1].x - pts1[i].x; - tempy = pts1[i+1].y - pts1[i].y; - if(i==0) - { - pts2[i+1].x = point.x + tempx; - pts2[i+1].y = point.y + tempy; - } - else if(i>0) - { - pts2[i+1].x = pts2[i].x + tempx; - pts2[i+1].y = pts2[i].y + tempy; - } - - } - - for(int i=flag;i im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0) - { - cout << "Index out of range" << endl; - exit(0); - } - - final1 = Mat::zeros(img2.size(),CV_8UC3); - res = Mat::zeros(img2.size(),CV_8UC1); - for(int i=miny, k=minyd;i<(miny+leny);i++,k++) - for(int j=minx,l=minxd ;j<(minx+lenx);j++,l++) - { - for(int c=0;c(k,l*channel+c) = final.at(i,j*channel+c); - - } - } - - - const Point* pts6[1] = {&pts2[0]}; - fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0); - - if(num == 1 || num == 2 || num == 3) - { - Cloning obj; - obj.normal_clone(img2,final1,res,blend,num); - namedWindow("Cloned Image"); - imshow("Cloned Image", blend); - waitKey(0); - } - - for(int i = 0; i < flag ; i++) - { - pts2[i].x=0; - pts2[i].y=0; - } - - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; - } - - im1.release(); -} - -void cv::seamlessClone(InputArray _src, InputArray _dst, OutputArray _blend, int flags) +void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags) { Mat src = _src.getMat(); Mat dest = _dst.getMat(); + Mat mask = _mask.getMat(); _blend.create(dest.size(), CV_8UC3); - blend = _blend.getMat(); + Mat blend = _blend.getMat(); - num = flags; + int minx = INT_MAX, miny = INT_MAX, maxx = INT_MIN, maxy = INT_MIN; + int h = mask.size().height; + int w = mask.size().width; - minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + Mat gray = Mat(mask.size(),CV_8UC1); + Mat dst_mask = Mat::zeros(dest.size(),CV_8UC1); + Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); + Mat cd_mask = Mat::zeros(dest.size(),CV_8UC3); - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + if(mask.channels() == 3) + cvtColor(mask, gray, COLOR_BGR2GRAY ); + else + gray = mask; - img0 = src; - img2 = dest; + for(int i=0;i(i,j) == 255) + { + minx = std::min(minx,i); + maxx = std::max(maxx,i); + miny = std::min(miny,j); + maxy = std::max(maxy,j); + } + } + } - channel = img0.channels(); + int lenx = maxx - minx; + int leny = maxy - miny; - res = Mat::zeros(img2.size(),CV_8UC1); - res1 = Mat::zeros(img0.size(),CV_8UC1); - final = Mat::zeros(img0.size(),CV_8UC3); - final1 = Mat::zeros(img2.size(),CV_8UC3); - //////////// source image /////////////////// + int minxd = p.y - lenx/2; + int maxxd = p.y + lenx/2; + int minyd = p.x - leny/2; + int maxyd = p.x + leny/2; - namedWindow("Source", 1); - setMouseCallback("Source", mouseHandler, NULL); - imshow("Source", img0); + if(minxd < 0 || minyd < 0 || maxxd > dest.size().height || maxyd > dest.size().width) + { + cout << "Index out of range" << endl; + exit(0); + } - /////////// destination image /////////////// + for(int i=minx, k=minxd;i<(minx+lenx);i++,k++) + for(int j=miny,l=minyd ;j<(miny+leny);j++,l++) + { + dst_mask.at(k,l) = gray.at(i,j); + } - namedWindow("Destination", 1); - setMouseCallback("Destination", mouseHandler1, NULL); - imshow("Destination",img2); - waitKey(0); + int channel = 3; - img0.release(); - img1.release(); - img2.release(); + for(int i=minx;i<(minx+lenx);i++) + for(int j=miny;j<(miny+leny);j++) + { + for(int c=0;c<3;c++) + { + if(gray.at(i,j) == 255) + cs_mask.at(i,j*channel+c) = src.at(i,j*channel+c); + } + } + + for(int i=minx, k=minxd;i<(minx+lenx);i++,k++) + for(int j=miny,l=minyd ;j<(miny+leny);j++,l++) + { + for(int c=0;c(k,l*channel+c) = cs_mask.at(i,j*channel+c); + } + + Cloning obj; + obj.normal_clone(dest,cd_mask,dst_mask,blend,flags); } -void cv::colorChange(InputArray _src, OutputArray _dst, int flags, float r, float g, float b) +void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float r, float g, float b) { Mat src = _src.getMat(); + Mat mask = _mask.getMat(); _dst.create(src.size(), src.type()); - blend = _dst.getMat(); + Mat blend = _dst.getMat(); - minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + float red = r; + float green = g; + float blue = b; - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + Mat gray = Mat::zeros(mask.size(),CV_8UC1); + cvtColor(mask, gray, COLOR_BGR2GRAY); - num = flags; - red = r; - green = g; - blue = b; + Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); - img0 = src; - res1 = Mat::zeros(img0.size(),CV_8UC1); - final = Mat::zeros(img0.size(),CV_8UC3); + int channel = 3; + for(int i=0;i(i,j) == 255) + { + for(int c=0;c(i,j*channel+c) = src.at(i,j*channel+c); + } + } - namedWindow("Source"); - setMouseCallback("Source", mouseHandler, NULL); - imshow("Source", img0); + } - waitKey(0); - - img0.release(); + Cloning obj; + obj.local_color_change(src,cs_mask,gray,blend,red,green,blue); } -void cv::illuminationChange(InputArray _src, OutputArray _dst, float a, float b) +void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float a, float b) { Mat src = _src.getMat(); + Mat mask = _mask.getMat(); _dst.create(src.size(), src.type()); - blend = _dst.getMat(); - num = 6; - alpha = a; - beta = b; + Mat blend = _dst.getMat(); + float alpha = a; + float beta = b; - img0 = src; + Mat gray = Mat::zeros(mask.size(),CV_8UC1); + cvtColor(mask, gray, COLOR_BGR2GRAY); - res1 = Mat::zeros(img0.size(),CV_8UC1); - final = Mat::zeros(img0.size(),CV_8UC3); + Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); - namedWindow("Source"); - setMouseCallback("Source", mouseHandler, NULL); - imshow("Source", img0); + int channel = 3; + for(int i=0;i(i,j) == 255) + { + for(int c=0;c(i,j*channel+c) = src.at(i,j*channel+c); + } + } + + } + + Cloning obj; + obj.illum_change(src,cs_mask,gray,blend,alpha,beta); - waitKey(0); } void cv::textureFlattening(InputArray _src, OutputArray _dst) { Mat src = _src.getMat(); _dst.create(src.size(), src.type()); - blend = _dst.getMat(); - img0 = src; + Mat blend = _dst.getMat(); Cloning obj; - obj.texture_flatten(img0,blend); - - namedWindow("Texture Flattened Image"); - imshow("Texture Flattened Image", blend); - waitKey(0); - + obj.texture_flatten(src,blend); } diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index acff7059b4..61fdad9c5e 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -1,3 +1,45 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" @@ -15,822 +57,819 @@ using namespace cv; class Cloning { - - public: - - Mat grx,gry,sgx,sgy,r_channel,g_channel,b_channel,smask1,grx32,gry32; - Mat smask,srx32,sry32; - Mat rx_channel,ry_channel,gx_channel,gy_channel,bx_channel,by_channel,resultr,resultg,resultb; - void init(Mat &I, Mat &wmask); - void calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy); - void getGradientx(const Mat &img, Mat &gx); - void getGradienty(const Mat &img, Mat &gy); - void lapx(const Mat &img, Mat &gxx); - void lapy(const Mat &img, Mat &gyy); - void dst(double *gtest, double *gfinal,int h,int w); - void idst(double *gtest, double *gfinal,int h,int w); - void transpose(double *mat, double *mat_t,int h,int w); - void poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result); - void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num); - void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num, float red, float green, float blue); - void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta); - void texture_flatten(Mat &I, Mat &final); - }; - + + public: + + Mat grx,gry,sgx,sgy,r_channel,g_channel,b_channel,smask1,grx32,gry32; + Mat smask,srx32,sry32; + Mat rx_channel,ry_channel,gx_channel,gy_channel,bx_channel,by_channel,resultr,resultg,resultb; + void init(Mat &I, Mat &wmask); + void calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy); + void getGradientx(const Mat &img, Mat &gx); + void getGradienty(const Mat &img, Mat &gy); + void lapx(const Mat &img, Mat &gxx); + void lapy(const Mat &img, Mat &gyy); + void dst(double *gtest, double *gfinal,int h,int w); + void idst(double *gtest, double *gfinal,int h,int w); + void transpose(double *mat, double *mat_t,int h,int w); + void poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result); + void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num); + void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red, float green, float blue); + void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta); + void texture_flatten(Mat &I, Mat &final); +}; + void Cloning::getGradientx( const Mat &img, Mat &gx) { - int w = img.size().width; - int h = img.size().height; - int channel = img.channels(); + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); - gx = Mat::zeros(img.size(),CV_32FC3); - for(int i=0;i(i,j*channel+c) = - (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); - } + gx = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i,j*channel+c) = + (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); + } } void Cloning::getGradienty( const Mat &img, Mat &gy) { - int w = img.size().width; - int h = img.size().height; - int channel = img.channels(); + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); - gy = Mat::zeros(img.size(),CV_32FC3); - for(int i=0;i(i,j*channel+c) = - (float)img.at((i+1),j*channel+c) - (float)img.at(i,j*channel+c); - - } + gy = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i,j*channel+c) = + (float)img.at((i+1),j*channel+c) - (float)img.at(i,j*channel+c); + + } } void Cloning::lapx( const Mat &img, Mat &gxx) { - int w = img.size().width; - int h = img.size().height; - int channel = img.channels(); + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); - gxx = Mat::zeros(img.size(),CV_32FC3); - for(int i=0;i(i,(j+1)*channel+c) = - (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); - } + gxx = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i,(j+1)*channel+c) = + (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); + } } void Cloning::lapy( const Mat &img, Mat &gyy) { - int w = img.size().width; - int h = img.size().height; - int channel = img.channels(); - gyy = Mat::zeros(img.size(),CV_32FC3); - for(int i=0;i(i+1,j*channel+c) = - (float)img.at((i+1),j*channel+c) - (float)img.at(i,j*channel+c); - - } + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); + gyy = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i+1,j*channel+c) = + (float)img.at((i+1),j*channel+c) - (float)img.at(i,j*channel+c); + + } } void Cloning::dst(double *gtest, double *gfinal,int h,int w) { - unsigned long int idx; + unsigned long int idx; - Mat temp = Mat(2*h+2,1,CV_32F); - Mat res = Mat(h,1,CV_32F); + Mat temp = Mat(2*h+2,1,CV_32F); + Mat res = Mat(h,1,CV_32F); - Mat planes[] = {Mat_(temp), Mat::zeros(temp.size(), CV_32F)}; + Mat planes[] = {Mat_(temp), Mat::zeros(temp.size(), CV_32F)}; - Mat complex1; - int p=0; - for(int i=0;i(0,0) = 0.0; - - for(int j=0,r=1;j(r,0) = gtest[idx]; - } + Mat complex1; + int p=0; + for(int i=0;i(0,0) = 0.0; - temp.at(h+1,0)=0.0; + for(int j=0,r=1;j(r,0) = gtest[idx]; + } - for(int j=h-1, r=h+2;j>=0;j--,r++) - { - idx = j*w+i; - temp.at(r,0) = -1*gtest[idx]; - } - - merge(planes, 2, complex1); + temp.at(h+1,0)=0.0; - dft(complex1,complex1,0,0); + for(int j=h-1, r=h+2;j>=0;j--,r++) + { + idx = j*w+i; + temp.at(r,0) = -1*gtest[idx]; + } - Mat planes1[] = {Mat::zeros(complex1.size(), CV_32F), Mat::zeros(complex1.size(), CV_32F)}; - - split(complex1, planes1); + merge(planes, 2, complex1); - std::complex two_i = std::sqrt(std::complex(-1)); + dft(complex1,complex1,0,0); - double fac = -2*imag(two_i); + Mat planes1[] = {Mat::zeros(complex1.size(), CV_32F), Mat::zeros(complex1.size(), CV_32F)}; - for(int c=1,z=0;c(z,0) = planes1[1].at(c,0)/fac; - } + split(complex1, planes1); - for(int q=0,z=0;q(z,0); - } - p++; - } + std::complex two_i = std::sqrt(std::complex(-1)); - temp.release(); - res.release(); - planes[0].release(); - planes[1].release(); + double fac = -2*imag(two_i); + + for(int c=1,z=0;c(z,0) = planes1[1].at(c,0)/fac; + } + + for(int q=0,z=0;q(z,0); + } + p++; + } + + temp.release(); + res.release(); + planes[0].release(); + planes[1].release(); } void Cloning::idst(double *gtest, double *gfinal,int h,int w) { - int nn = h+1; - unsigned long int idx; - dst(gtest,gfinal,h,w); - for(int i= 0;i(i,j) = mat[idx]; - } - } - Mat tmp_t = tmp.t(); + idx = i*(w) + j; + tmp.at(i,j) = mat[idx]; + } + } + Mat tmp_t = tmp.t(); - for(int i = 0;i < tmp_t.size().height; i++) - for(int j=0;j(i,j); - } + for(int i = 0;i < tmp_t.size().height; i++) + for(int j=0;j(i,j); + } - tmp.release(); + tmp.release(); } void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) { - int w = img.size().width; - int h = img.size().height; + int w = img.size().width; + int h = img.size().height; - unsigned long int idx,idx1; + unsigned long int idx,idx1; - Mat lap = Mat(img.size(),CV_32FC1); + Mat lap = Mat(img.size(),CV_32FC1); - for(int i =0;i(i,j)=gyy.at(i,j)+gxx.at(i,j); + for(int i =0;i(i,j)=gyy.at(i,j)+gxx.at(i,j); - Mat bound = img.clone(); + Mat bound = img.clone(); - for(int i =1;i(i,j) = 0.0; - } - - double *f_bp = new double[h*w]; + for(int i =1;i(i,j) = 0.0; + } + + double *f_bp = new double[h*w]; - for(int i =1;i(i,j) + (int)bound.at(i,(j+1)) + (int)bound.at(i,(j-1)) - + (int)bound.at(i-1,j) + (int)bound.at(i+1,j); - } - - - Mat diff = Mat(h,w,CV_32FC1); - for(int i =0;i(i,j) = (lap.at(i,j) - f_bp[idx]); - } - } - - lap.release(); - - double *gtest = new double[(h-2)*(w-2)]; - for(int i = 0 ; i < h-2;i++) - { - for(int j = 0 ; j < w-2; j++) - { - idx = i*(w-2) + j; - gtest[idx] = diff.at(i+1,j+1); - - } - } - - diff.release(); - ///////////////////////////////////////////////////// Find DST ///////////////////////////////////////////////////// - - double *gfinal = new double[(h-2)*(w-2)]; - double *gfinal_t = new double[(h-2)*(w-2)]; - double *denom = new double[(h-2)*(w-2)]; - double *f3 = new double[(h-2)*(w-2)]; - double *f3_t = new double[(h-2)*(w-2)]; - double *img_d = new double[(h)*(w)]; - - dst(gtest,gfinal,h-2,w-2); - - transpose(gfinal,gfinal_t,h-2,w-2); - - dst(gfinal_t,gfinal,w-2,h-2); - - transpose(gfinal,gfinal_t,w-2,h-2); - - int cy=1; - - for(int i = 0 ; i < w-2;i++,cy++) - { - for(int j = 0,cx = 1; j < h-2; j++,cx++) - { - idx = j*(w-2) + i; - denom[idx] = (float) 2*cos(pi*cy/( (double) (w-1))) - 2 + 2*cos(pi*cx/((double) (h-1))) - 2; - - } - } - - for(idx = 0 ; idx < (unsigned)(w-2)*(h-2) ;idx++) - { - gfinal_t[idx] = gfinal_t[idx]/denom[idx]; - } + for(int i =1;i(i,j) + (int)bound.at(i,(j+1)) + (int)bound.at(i,(j-1)) + + (int)bound.at(i-1,j) + (int)bound.at(i+1,j); + } - idst(gfinal_t,f3,h-2,w-2); + Mat diff = Mat(h,w,CV_32FC1); + for(int i =0;i(i,j) = (lap.at(i,j) - f_bp[idx]); + } + } - transpose(f3,f3_t,h-2,w-2); + lap.release(); - idst(f3_t,f3,w-2,h-2); + double *gtest = new double[(h-2)*(w-2)]; + for(int i = 0 ; i < h-2;i++) + { + for(int j = 0 ; j < w-2; j++) + { + idx = i*(w-2) + j; + gtest[idx] = diff.at(i+1,j+1); - transpose(f3,f3_t,w-2,h-2); + } + } - for(int i = 0 ; i < h;i++) - { - for(int j = 0 ; j < w; j++) - { - idx = i*w + j; - img_d[idx] = (double)img.at(i,j); - } - } - for(int i = 1 ; i < h-1;i++) - { - for(int j = 1 ; j < w-1; j++) - { - idx = i*w + j; - img_d[idx] = 0.0; - } - } - for(int i = 1,id1=0 ; i < h-1;i++,id1++) - { - for(int j = 1,id2=0 ; j < w-1; j++,id2++) - { - idx = i*w + j; - idx1= id1*(w-2) + id2; - img_d[idx] = f3_t[idx1]; - } - } - - for(int i = 0 ; i < h;i++) - { - for(int j = 0 ; j < w; j++) - { - idx = i*w + j; - if(img_d[idx] < 0.0) - result.at(i,j) = 0; - else if(img_d[idx] > 255.0) - result.at(i,j) = 255.0; - else - result.at(i,j) = img_d[idx]; - } - } + diff.release(); + ///////////////////////////////////////////////////// Find DST ///////////////////////////////////////////////////// - delete [] gfinal; - delete [] gfinal_t; - delete [] denom; - delete [] f3; - delete [] f3_t; - delete [] img_d; - delete [] gtest; - delete [] f_bp; + double *gfinal = new double[(h-2)*(w-2)]; + double *gfinal_t = new double[(h-2)*(w-2)]; + double *denom = new double[(h-2)*(w-2)]; + double *f3 = new double[(h-2)*(w-2)]; + double *f3_t = new double[(h-2)*(w-2)]; + double *img_d = new double[(h)*(w)]; + + dst(gtest,gfinal,h-2,w-2); + + transpose(gfinal,gfinal_t,h-2,w-2); + + dst(gfinal_t,gfinal,w-2,h-2); + + transpose(gfinal,gfinal_t,w-2,h-2); + + int cy=1; + + for(int i = 0 ; i < w-2;i++,cy++) + { + for(int j = 0,cx = 1; j < h-2; j++,cx++) + { + idx = j*(w-2) + i; + denom[idx] = (float) 2*cos(pi*cy/( (double) (w-1))) - 2 + 2*cos(pi*cx/((double) (h-1))) - 2; + + } + } + + for(idx = 0 ; idx < (unsigned)(w-2)*(h-2) ;idx++) + { + gfinal_t[idx] = gfinal_t[idx]/denom[idx]; + } + + + idst(gfinal_t,f3,h-2,w-2); + + transpose(f3,f3_t,h-2,w-2); + + idst(f3_t,f3,w-2,h-2); + + transpose(f3,f3_t,w-2,h-2); + + for(int i = 0 ; i < h;i++) + { + for(int j = 0 ; j < w; j++) + { + idx = i*w + j; + img_d[idx] = (double)img.at(i,j); + } + } + for(int i = 1 ; i < h-1;i++) + { + for(int j = 1 ; j < w-1; j++) + { + idx = i*w + j; + img_d[idx] = 0.0; + } + } + for(int i = 1,id1=0 ; i < h-1;i++,id1++) + { + for(int j = 1,id2=0 ; j < w-1; j++,id2++) + { + idx = i*w + j; + idx1= id1*(w-2) + id2; + img_d[idx] = f3_t[idx1]; + } + } + + for(int i = 0 ; i < h;i++) + { + for(int j = 0 ; j < w; j++) + { + idx = i*w + j; + if(img_d[idx] < 0.0) + result.at(i,j) = 0; + else if(img_d[idx] > 255.0) + result.at(i,j) = 255.0; + else + result.at(i,j) = img_d[idx]; + } + } + + delete [] gfinal; + delete [] gfinal_t; + delete [] denom; + delete [] f3; + delete [] f3_t; + delete [] img_d; + delete [] gtest; + delete [] f_bp; } void Cloning::init(Mat &I, Mat &wmask) { - grx = Mat(I.size(),CV_32FC3); - gry = Mat(I.size(),CV_32FC3); - sgx = Mat(I.size(),CV_32FC3); - sgy = Mat(I.size(),CV_32FC3); - - r_channel = Mat::zeros(I.size(),CV_8UC1); - g_channel = Mat::zeros(I.size(),CV_8UC1); - b_channel = Mat::zeros(I.size(),CV_8UC1); + grx = Mat(I.size(),CV_32FC3); + gry = Mat(I.size(),CV_32FC3); + sgx = Mat(I.size(),CV_32FC3); + sgy = Mat(I.size(),CV_32FC3); - for(int i=0;i(i,j) = I.at(i,j*3+0); - g_channel.at(i,j) = I.at(i,j*3+1); - b_channel.at(i,j) = I.at(i,j*3+2); - } + r_channel = Mat::zeros(I.size(),CV_8UC1); + g_channel = Mat::zeros(I.size(),CV_8UC1); + b_channel = Mat::zeros(I.size(),CV_8UC1); - smask = Mat(wmask.size(),CV_32FC1); - srx32 = Mat(I.size(),CV_32FC3); - sry32 = Mat(I.size(),CV_32FC3); - smask1 = Mat(wmask.size(),CV_32FC1); - grx32 = Mat(I.size(),CV_32FC3); - gry32 = Mat(I.size(),CV_32FC3); + for(int i=0;i(i,j) = I.at(i,j*3+0); + g_channel.at(i,j) = I.at(i,j*3+1); + b_channel.at(i,j) = I.at(i,j*3+2); + } + + smask = Mat(wmask.size(),CV_32FC1); + srx32 = Mat(I.size(),CV_32FC3); + sry32 = Mat(I.size(),CV_32FC3); + smask1 = Mat(wmask.size(),CV_32FC1); + grx32 = Mat(I.size(),CV_32FC3); + gry32 = Mat(I.size(),CV_32FC3); } void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) { - int channel = I.channels(); - Mat fx = Mat(I.size(),CV_32FC3); - Mat fy = Mat(I.size(),CV_32FC3); + int channel = I.channels(); + Mat fx = Mat(I.size(),CV_32FC3); + Mat fy = Mat(I.size(),CV_32FC3); - for(int i=0;i < I.size().height; i++) - for(int j=0; j < I.size().width; j++) - for(int c=0;c(i,j*channel+c) = - (gx.at(i,j*channel+c)+sx.at(i,j*channel+c)); - fy.at(i,j*channel+c) = - (gy.at(i,j*channel+c)+sy.at(i,j*channel+c)); - } + for(int i=0;i < I.size().height; i++) + for(int j=0; j < I.size().width; j++) + for(int c=0;c(i,j*channel+c) = + (gx.at(i,j*channel+c)+sx.at(i,j*channel+c)); + fy.at(i,j*channel+c) = + (gy.at(i,j*channel+c)+sy.at(i,j*channel+c)); + } - Mat gxx = Mat(I.size(),CV_32FC3); - Mat gyy = Mat(I.size(),CV_32FC3); + Mat gxx = Mat(I.size(),CV_32FC3); + Mat gyy = Mat(I.size(),CV_32FC3); - lapx(fx,gxx); - lapy(fy,gyy); + lapx(fx,gxx); + lapy(fy,gyy); - rx_channel = Mat(I.size(),CV_32FC1); - gx_channel = Mat(I.size(),CV_32FC1); - bx_channel = Mat(I.size(),CV_32FC1); - - for(int i=0;i(i,j) = gxx.at(i,j*3+0); - gx_channel.at(i,j) = gxx.at(i,j*3+1); - bx_channel.at(i,j) = gxx.at(i,j*3+2); - } - - ry_channel = Mat(I.size(),CV_32FC1); - gy_channel = Mat(I.size(),CV_32FC1); - by_channel = Mat(I.size(),CV_32FC1); - - for(int i=0;i(i,j) = gyy.at(i,j*3+0); - gy_channel.at(i,j) = gyy.at(i,j*3+1); - by_channel.at(i,j) = gyy.at(i,j*3+2); - } + rx_channel = Mat(I.size(),CV_32FC1); + gx_channel = Mat(I.size(),CV_32FC1); + bx_channel = Mat(I.size(),CV_32FC1); - resultr = Mat(I.size(),CV_8UC1); - resultg = Mat(I.size(),CV_8UC1); - resultb = Mat(I.size(),CV_8UC1); + for(int i=0;i(i,j) = gxx.at(i,j*3+0); + gx_channel.at(i,j) = gxx.at(i,j*3+1); + bx_channel.at(i,j) = gxx.at(i,j*3+2); + } - clock_t tic = clock(); + ry_channel = Mat(I.size(),CV_32FC1); + gy_channel = Mat(I.size(),CV_32FC1); + by_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gyy.at(i,j*3+0); + gy_channel.at(i,j) = gyy.at(i,j*3+1); + by_channel.at(i,j) = gyy.at(i,j*3+2); + } + + resultr = Mat(I.size(),CV_8UC1); + resultg = Mat(I.size(),CV_8UC1); + resultb = Mat(I.size(),CV_8UC1); + + clock_t tic = clock(); - poisson_solver(r_channel,rx_channel, ry_channel,resultr); - poisson_solver(g_channel,gx_channel, gy_channel,resultg); - poisson_solver(b_channel,bx_channel, by_channel,resultb); + poisson_solver(r_channel,rx_channel, ry_channel,resultr); + poisson_solver(g_channel,gx_channel, gy_channel,resultg); + poisson_solver(b_channel,bx_channel, by_channel,resultb); - clock_t toc = clock(); + clock_t toc = clock(); - printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); + printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); } void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num) { - init(I,wmask); + init(I,wmask); - int w = I.size().width; - int h = I.size().height; - int channel = I.channels(); + int w = I.size().width; + int h = I.size().height; + int channel = I.channels(); - getGradientx(I,grx); - getGradienty(I,gry); + getGradientx(I,grx); + getGradienty(I,gry); - if(num != 3) - { - getGradientx(mask,sgx); - getGradienty(mask,sgy); - } + if(num != 3) + { + getGradientx(mask,sgx); + getGradienty(mask,sgy); + } - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); - - if(num == 1) - { - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); - } - else if(num == 2) - { - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) - sgy.at(i,j*channel+c)) > - abs(grx.at(i,j*channel+c) - gry.at(i,j*channel+c))) - { + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); - srx32.at(i,j*channel+c) = sgx.at(i,j*channel+c) - * smask.at(i,j); - sry32.at(i,j*channel+c) = sgy.at(i,j*channel+c) - * smask.at(i,j); - } - else - { - srx32.at(i,j*channel+c) = grx.at(i,j*channel+c) - * smask.at(i,j); - sry32.at(i,j*channel+c) = gry.at(i,j*channel+c) - * smask.at(i,j); - } - } - } - else if(num == 3) - { - Mat gray = Mat(mask.size(),CV_8UC1); - Mat gray8 = Mat(mask.size(),CV_8UC3); - cvtColor(mask, gray, COLOR_BGR2GRAY ); - - for(int i=0;i(i,j*3+0) = gray.at(i,j); - gray8.at(i,j*3+1) = gray.at(i,j); - gray8.at(i,j*3+2) = gray.at(i,j); - } + if(num == 1) + { + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + + } + else if(num == 2) + { + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) - sgy.at(i,j*channel+c)) > + abs(grx.at(i,j*channel+c) - gry.at(i,j*channel+c))) + { + + srx32.at(i,j*channel+c) = sgx.at(i,j*channel+c) + * smask.at(i,j); + sry32.at(i,j*channel+c) = sgy.at(i,j*channel+c) + * smask.at(i,j); + } + else + { + srx32.at(i,j*channel+c) = grx.at(i,j*channel+c) + * smask.at(i,j); + sry32.at(i,j*channel+c) = gry.at(i,j*channel+c) + * smask.at(i,j); + } + } + } + else if(num == 3) + { + Mat gray = Mat(mask.size(),CV_8UC1); + Mat gray8 = Mat(mask.size(),CV_8UC3); + cvtColor(mask, gray, COLOR_BGR2GRAY ); + + for(int i=0;i(i,j*3+0) = gray.at(i,j); + gray8.at(i,j*3+1) = gray.at(i,j); + gray8.at(i,j*3+2) = gray.at(i,j); + } - getGradientx(gray8,sgx); - getGradienty(gray8,sgy); + getGradientx(gray8,sgx); + getGradienty(gray8,sgy); - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } - - } + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } - bitwise_not(wmask,wmask); + } - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } + bitwise_not(wmask,wmask); - calc(I,grx32,gry32,srx32,sry32); + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } + + calc(I,grx32,gry32,srx32,sry32); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } } -void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num, float red=1.0, float green=1.0, float blue=1.0) +void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red=1.0, float green=1.0, float blue=1.0) { - init(I,wmask); + init(I,wmask); - int w = I.size().width; - int h = I.size().height; - int channel = I.channels(); + int w = I.size().width; + int h = I.size().height; + int channel = I.channels(); - getGradientx(I,grx); - getGradienty(I,gry); + getGradientx(I,grx); + getGradienty(I,gry); - getGradientx(mask,sgx); - getGradienty(mask,sgy); + getGradientx(mask,sgx); + getGradienty(mask,sgy); - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); - if(num == 4) - { - Mat factor = Mat(I.size(),CV_32FC3); + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - { - factor.at(i,j*channel+0) = blue; - factor.at(i,j*channel+1) = green; - factor.at(i,j*channel+2) = red; - } + Mat factor = Mat(I.size(),CV_32FC3); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + { + factor.at(i,j*channel+0) = blue; + factor.at(i,j*channel+1) = green; + factor.at(i,j*channel+2) = red; + } - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - srx32.at(i,j*channel+c)*factor.at(i,j*channel+c); - sry32.at(i,j*channel+c) = - sry32.at(i,j*channel+c)*factor.at(i,j*channel+c); - } - } + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + srx32.at(i,j*channel+c)*factor.at(i,j*channel+c); + sry32.at(i,j*channel+c) = + sry32.at(i,j*channel+c)*factor.at(i,j*channel+c); + } - bitwise_not(wmask,wmask); + bitwise_not(wmask,wmask); - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } - calc(I,grx32,gry32,srx32,sry32); + calc(I,grx32,gry32,srx32,sry32); - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } } void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta) { - init(I,wmask); + init(I,wmask); - int w = I.size().width; - int h = I.size().height; - int channel = I.channels(); + int w = I.size().width; + int h = I.size().height; + int channel = I.channels(); - getGradientx(I,grx); - getGradienty(I,gry); + getGradientx(I,grx); + getGradienty(I,gry); - getGradientx(mask,sgx); - getGradienty(mask,sgy); + getGradientx(mask,sgx); + getGradienty(mask,sgy); - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } - Mat mag = Mat(I.size(),CV_32FC3); - I.convertTo(mag,CV_32FC3,1.0/255.0); + Mat mag = Mat(I.size(),CV_32FC3); + I.convertTo(mag,CV_32FC3,1.0/255.0); - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - sqrt(pow(srx32.at(i,j*channel+c),2) + pow(sry32.at(i,j*channel+c),2)); - } - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) != 0) - { - srx32.at(i,j*channel+c) = - pow(alpha,beta)*srx32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); - sry32.at(i,j*channel+c) = - pow(alpha,beta)*sry32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); - } - } + mag.at(i,j*channel+c) = + sqrt(pow(srx32.at(i,j*channel+c),2) + pow(sry32.at(i,j*channel+c),2)); + } - bitwise_not(wmask,wmask); + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) != 0) + { + srx32.at(i,j*channel+c) = + pow(alpha,beta)*srx32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); + sry32.at(i,j*channel+c) = + pow(alpha,beta)*sry32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); + } + } - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); + bitwise_not(wmask,wmask); - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); - calc(I,grx32,gry32,srx32,sry32); + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + calc(I,grx32,gry32,srx32,sry32); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } } void Cloning::texture_flatten(Mat &I, Mat &final) { - grx = Mat(I.size(),CV_32FC3); - gry = Mat(I.size(),CV_32FC3); + grx = Mat(I.size(),CV_32FC3); + gry = Mat(I.size(),CV_32FC3); - Mat out = Mat(I.size(),CV_8UC1); + Mat out = Mat(I.size(),CV_8UC1); - getGradientx( I, grx); - getGradienty( I, gry); + getGradientx( I, grx); + getGradienty( I, gry); - Canny( I, out, 30, 45, 3 ); + Canny( I, out, 30, 45, 3 ); - int channel = I.channels(); + int channel = I.channels(); - for(int i=0;i(i,j) != 255) - { - grx.at(i,j*channel+c) = 0.0; - gry.at(i,j*channel+c) = 0.0; - } - } + for(int i=0;i(i,j) != 255) + { + grx.at(i,j*channel+c) = 0.0; + gry.at(i,j*channel+c) = 0.0; + } + } - r_channel = Mat::zeros(I.size(),CV_8UC1); - g_channel = Mat::zeros(I.size(),CV_8UC1); - b_channel = Mat::zeros(I.size(),CV_8UC1); + r_channel = Mat::zeros(I.size(),CV_8UC1); + g_channel = Mat::zeros(I.size(),CV_8UC1); + b_channel = Mat::zeros(I.size(),CV_8UC1); - for(int i=0;i(i,j) = I.at(i,j*3+0); - g_channel.at(i,j) = I.at(i,j*3+1); - b_channel.at(i,j) = I.at(i,j*3+2); - } + for(int i=0;i(i,j) = I.at(i,j*3+0); + g_channel.at(i,j) = I.at(i,j*3+1); + b_channel.at(i,j) = I.at(i,j*3+2); + } - Mat gxx = Mat(I.size(),CV_32FC3); - Mat gyy = Mat(I.size(),CV_32FC3); + Mat gxx = Mat(I.size(),CV_32FC3); + Mat gyy = Mat(I.size(),CV_32FC3); - lapx(grx,gxx); - lapy(gry,gyy); + lapx(grx,gxx); + lapy(gry,gyy); - rx_channel = Mat(I.size(),CV_32FC1); - gx_channel = Mat(I.size(),CV_32FC1); - bx_channel = Mat(I.size(),CV_32FC1); - - for(int i=0;i(i,j) = gxx.at(i,j*3+0); - gx_channel.at(i,j) = gxx.at(i,j*3+1); - bx_channel.at(i,j) = gxx.at(i,j*3+2); - } - - ry_channel = Mat(I.size(),CV_32FC1); - gy_channel = Mat(I.size(),CV_32FC1); - by_channel = Mat(I.size(),CV_32FC1); - - for(int i=0;i(i,j) = gyy.at(i,j*3+0); - gy_channel.at(i,j) = gyy.at(i,j*3+1); - by_channel.at(i,j) = gyy.at(i,j*3+2); - } + rx_channel = Mat(I.size(),CV_32FC1); + gx_channel = Mat(I.size(),CV_32FC1); + bx_channel = Mat(I.size(),CV_32FC1); - resultr = Mat(I.size(),CV_8UC1); - resultg = Mat(I.size(),CV_8UC1); - resultb = Mat(I.size(),CV_8UC1); + for(int i=0;i(i,j) = gxx.at(i,j*3+0); + gx_channel.at(i,j) = gxx.at(i,j*3+1); + bx_channel.at(i,j) = gxx.at(i,j*3+2); + } - clock_t tic = clock(); + ry_channel = Mat(I.size(),CV_32FC1); + gy_channel = Mat(I.size(),CV_32FC1); + by_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gyy.at(i,j*3+0); + gy_channel.at(i,j) = gyy.at(i,j*3+1); + by_channel.at(i,j) = gyy.at(i,j*3+2); + } + + resultr = Mat(I.size(),CV_8UC1); + resultg = Mat(I.size(),CV_8UC1); + resultb = Mat(I.size(),CV_8UC1); + + clock_t tic = clock(); - poisson_solver(r_channel,rx_channel, ry_channel,resultr); - poisson_solver(g_channel,gx_channel, gy_channel,resultg); - poisson_solver(b_channel,bx_channel, by_channel,resultb); + poisson_solver(r_channel,rx_channel, ry_channel,resultr); + poisson_solver(g_channel,gx_channel, gy_channel,resultg); + poisson_solver(b_channel,bx_channel, by_channel,resultb); - clock_t toc = clock(); + clock_t toc = clock(); - printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); + printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } } diff --git a/modules/photo/test/test_cloning.cpp b/modules/photo/test/test_cloning.cpp new file mode 100644 index 0000000000..583a069aee --- /dev/null +++ b/modules/photo/test/test_cloning.cpp @@ -0,0 +1,179 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do 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, 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" +#include "opencv2/photo.hpp" +#include + +using namespace cv; +using namespace std; + + +TEST(Photo_SeamlessClone_normal, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Normal_Cloning/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1; + ASSERT_FALSE(destination.empty()) << "Could not load destination image " << original_path2; + ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path3; + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + seamlessClone(source, destination, mask, p, result, 1); + + imwrite(folder + "cloned.png", result); + +} + +TEST(Photo_SeamlessClone_mixed, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Mixed_Cloning/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1; + ASSERT_FALSE(destination.empty()) << "Could not load destination image " << original_path2; + ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path3; + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + seamlessClone(source, destination, mask, p, result, 2); + + imwrite(folder + "cloned.png", result); + +} + +TEST(Photo_SeamlessClone_featureExchange, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Feature_Exchange/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1; + ASSERT_FALSE(destination.empty()) << "Could not load destination image " << original_path2; + ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path3; + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + seamlessClone(source, destination, mask, p, result, 3); + + imwrite(folder + "cloned.png", result); + +} + +TEST(Photo_SeamlessClone_colorChange, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Color_Change/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1; + ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2; + + Mat result; + colorChange(source, mask, result, 1.5, .5, .5); + + imwrite(folder + "cloned.png", result); + +} + +TEST(Photo_SeamlessClone_illuminationChange, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Illumination_Change/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1; + ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2; + + Mat result; + illuminationChange(source, mask, result, .2, .4); + + imwrite(folder + "cloned.png", result); + +} + +TEST(Photo_SeamlessClone_textureFlattening, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Texture_Flattening/"; + string original_path = folder + "source1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path; + + Mat result; + textureFlattening(source, result); + + imwrite(folder + "cloned.png", result); + +} + diff --git a/modules/photo/test/test_decolor.cpp b/modules/photo/test/test_decolor.cpp index 94f78a7df0..c218c6a4fa 100644 --- a/modules/photo/test/test_decolor.cpp +++ b/modules/photo/test/test_decolor.cpp @@ -1,3 +1,45 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 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" #include "opencv2/photo.hpp" #include @@ -5,35 +47,22 @@ using namespace cv; using namespace std; -#ifdef DUMP_RESULTS -# define DUMP(image, path) imwrite(path, image) -#else -# define DUMP(image, path) -#endif - TEST(Photo_Decolor, regression) { string folder = string(cvtest::TS::ptr()->get_data_path()) + "decolor/"; string original_path = folder + "color_image_1.png"; - string expected_path1 = folder + "grayscale_image_1.png"; - string expected_path2 = folder + "color_boost_image_1.png"; Mat original = imread(original_path, IMREAD_COLOR); - Mat expected1 = imread(expected_path1, IMREAD_GRAYSCALE); - Mat expected2 = imread(expected_path2, IMREAD_COLOR); ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path; - ASSERT_FALSE(expected1.empty()) << "Could not load reference image " << expected_path1; - ASSERT_FALSE(expected2.empty()) << "Could not load reference image " << expected_path2; + ASSERT_FALSE(original.channels()!=3) << "Load color input image " << original_path; Mat grayscale, color_boost; decolor(original, grayscale, color_boost); - DUMP(grayscale, expected_path1 + ".grayscale.png"); - DUMP(color_boost, expected_path2 + ".color_boost.png"); + imwrite(folder + "grayscale.png",grayscale); + imwrite(folder + "color_boost.png",color_boost); - ASSERT_EQ(0, norm(grayscale != expected1)); - ASSERT_EQ(0, norm(color_boost != expected2)); } diff --git a/samples/cpp/cloning.cpp b/samples/cpp/cloning.cpp new file mode 100644 index 0000000000..70725d8e74 --- /dev/null +++ b/samples/cpp/cloning.cpp @@ -0,0 +1,288 @@ +/* +* cloning.cpp +* +* Author: +* Siddharth Kherada +* +* This tutorial demonstrates how to use OpenCV seamless cloning +* module. +* Flags: +* 1- NORMAL_CLONE +* 2- MIXED_CLONE +* 3- FEATURE_EXCHANGE + +* The program takes as input a source and a destination image +* and ouputs the cloned image. + +* Step 1: +* -> In the source image, select the region of interest by left click mouse button. A Polygon ROI will be created by left clicking mouse button. +* -> To set the Polygon ROI, click the right mouse button. +* -> To reset the region selected, click the middle mouse button. + +* Step 2: +* -> In the destination image, select the point where you want to place the ROI in the image by left clicking mouse button. +* -> To get the cloned result, click the right mouse button. + +* Result: The cloned image will be displayed. +*/ + +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include + +using namespace std; +using namespace cv; + +Mat img0, img1, img2, res, res1, final, final1, blend; + +Point point; +int drag = 0; +int destx, desty; + +int numpts = 100; +Point* pts = new Point[100]; +Point* pts2 = new Point[100]; +Point* pts_diff = new Point[100]; + + +int var = 0; +int flag = 0; +int flag1 = 0; + +int minx,miny,maxx,maxy,lenx,leny; +int minxd,minyd,maxxd,maxyd,lenxd,lenyd; + +int channel,num; + +void source(int event, int x, int y, int, void*) +{ + + if (event == EVENT_LBUTTONDOWN && !drag) + { + if(flag1 == 0) + { + if(var==0) + img1 = img0.clone(); + point = Point(x, y); + circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); + pts[var] = point; + var++; + drag = 1; + if(var>1) + line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); + + imshow("Source", img1); + } + } + + + if (event == EVENT_LBUTTONUP && drag) + { + imshow("Source", img1); + + drag = 0; + } + if (event == EVENT_RBUTTONDOWN) + { + flag1 = 1; + img1 = img0.clone(); + for(int i = var; i < numpts ; i++) + pts[i] = point; + + if(var!=0) + { + const Point* pts3[1] = {&pts[0]}; + polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); + } + + for(int i=0;i im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0) + { + cout << "Index out of range" << endl; + exit(0); + } + + final1 = Mat::zeros(img2.size(),CV_8UC3); + res = Mat::zeros(img2.size(),CV_8UC1); + for(int i=miny, k=minyd;i<(miny+leny);i++,k++) + for(int j=minx,l=minxd ;j<(minx+lenx);j++,l++) + { + for(int c=0;c(k,l*channel+c) = final.at(i,j*channel+c); + + } + } + + + const Point* pts6[1] = {&pts2[0]}; + fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0); + + if(num == 1 || num == 2 || num == 3) + { + seamlessClone(img0,img2,res1,point,blend,num); + imshow("Cloned Image", blend); + imwrite("cloned.png",blend); + waitKey(0); + } + + for(int i = 0; i < flag ; i++) + { + pts2[i].x=0; + pts2[i].y=0; + } + + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + } + + im1.release(); +} + +int main(int argc, char **argv) +{ + + if (argc != 3) + { + cout << "usage: " << argv[0] << " " << " " << endl; + exit(1); + } + + Mat src = imread(argv[1]); + Mat dest = imread(argv[2]); + + cout << "Flags:" << endl; + cout << "1- NORMAL_CLONE" << endl; + cout << "2- MIXED_CLONE" << endl; + cout << "3- FEATURE_EXCHANGE" << endl << endl; + + cout << "Enter Flag:"; + cin >> num; + + minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + + img0 = src; + img2 = dest; + + channel = img0.channels(); + + res = Mat::zeros(img2.size(),CV_8UC1); + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + final1 = Mat::zeros(img2.size(),CV_8UC3); + //////////// source image /////////////////// + + namedWindow("Source", 1); + setMouseCallback("Source", source, NULL); + imshow("Source", img0); + + /////////// destination image /////////////// + + namedWindow("Destination", 1); + setMouseCallback("Destination", destination, NULL); + imshow("Destination",img2); + waitKey(0); + + img0.release(); + img1.release(); + img2.release(); +} diff --git a/samples/cpp/create_mask.cpp b/samples/cpp/create_mask.cpp new file mode 100644 index 0000000000..03055e99e0 --- /dev/null +++ b/samples/cpp/create_mask.cpp @@ -0,0 +1,145 @@ + /* +* create_mask.cpp +* +* Author: +* Siddharth Kherada +* +* This tutorial demonstrates how to make mask image (black and white). +* The program takes as input a source image and ouputs its corresponding +* mask image. +*/ + + + +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include + +using namespace std; +using namespace cv; + +Mat img0, img1, res1, final; + +Point point; +int drag = 0; + +int numpts = 100; +Point* pts = new Point[100]; + +int var = 0; +int flag = 0; +int flag1 = 0; + +int minx,miny,maxx,maxy,lenx,leny; + +int channel; + +void mouseHandler(int event, int x, int y, int, void*) +{ + + if (event == EVENT_LBUTTONDOWN && !drag) + { + if(flag1 == 0) + { + if(var==0) + img1 = img0.clone(); + point = Point(x, y); + circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); + pts[var] = point; + var++; + drag = 1; + if(var>1) + line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); + + imshow("Source", img1); + } + } + + + if (event == EVENT_LBUTTONUP && drag) + { + imshow("Source", img1); + + drag = 0; + } + if (event == EVENT_RBUTTONDOWN) + { + flag1 = 1; + img1 = img0.clone(); + for(int i = var; i < numpts ; i++) + pts[i] = point; + + if(var!=0) + { + const Point* pts3[1] = {&pts[0]}; + polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); + } + + for(int i=0;i Date: Mon, 19 Aug 2013 13:16:04 +0530 Subject: [PATCH 22/97] added keyboard control --- modules/photo/include/opencv2/photo.hpp | 12 +- modules/photo/src/seamless_cloning.cpp | 43 ++- modules/photo/src/seamless_cloning.hpp | 122 +++---- modules/photo/test/test_cloning.cpp | 11 +- samples/cpp/cloning.cpp | 453 ++++++++++++++++++------ 5 files changed, 457 insertions(+), 184 deletions(-) diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 673670354f..d825c2489e 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -63,7 +63,13 @@ enum { NORMAL_CLONE = 1, MIXED_CLONE = 2, - FEATURE_EXCHANGE = 3 + MONOCHROME_TRANSFER = 3 +}; + +enum +{ + RECURSIVE_FILTER = 1, + NC_FILTER = 2 }; //! restores the damaged image areas using one of the available intpainting algorithms @@ -303,7 +309,9 @@ CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, float alpha = 0.2, float beta = 0.4); -CV_EXPORTS_W void textureFlattening(InputArray src, OutputArray dst); +CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst); + +CV_EXPORTS_W void edgepreservefilter(InputArray _src, OutputArray _dst, int flags = 1, float sigma_h = 60, float sigma_r = 0.4); } // cv diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp index c2d6c59b97..92beb02fe8 100644 --- a/modules/photo/src/seamless_cloning.cpp +++ b/modules/photo/src/seamless_cloning.cpp @@ -144,8 +144,12 @@ void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float float blue = b; Mat gray = Mat::zeros(mask.size(),CV_8UC1); - cvtColor(mask, gray, COLOR_BGR2GRAY); + if(mask.channels() == 3) + cvtColor(mask, gray, COLOR_BGR2GRAY ); + else + gray = mask; + Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); int channel = 3; @@ -178,7 +182,11 @@ void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float beta = b; Mat gray = Mat::zeros(mask.size(),CV_8UC1); - cvtColor(mask, gray, COLOR_BGR2GRAY); + + if(mask.channels() == 3) + cvtColor(mask, gray, COLOR_BGR2GRAY ); + else + gray = mask; Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); @@ -200,14 +208,39 @@ void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, obj.illum_change(src,cs_mask,gray,blend,alpha,beta); } -void cv::textureFlattening(InputArray _src, OutputArray _dst) + +void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst) { Mat src = _src.getMat(); + Mat mask = _mask.getMat(); _dst.create(src.size(), src.type()); Mat blend = _dst.getMat(); - Cloning obj; - obj.texture_flatten(src,blend); + Mat gray = Mat::zeros(mask.size(),CV_8UC1); + + if(mask.channels() == 3) + cvtColor(mask, gray, COLOR_BGR2GRAY ); + else + gray = mask; + + Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); + + int channel = 3; + for(int i=0;i(i,j) == 255) + { + for(int c=0;c(i,j*channel+c) = src.at(i,j*channel+c); + } + } + + } + + Cloning obj; + obj.texture_flatten(src,cs_mask,gray,blend); } diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index 61fdad9c5e..a59cb5d16b 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -76,7 +76,7 @@ class Cloning void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num); void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red, float green, float blue); void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta); - void texture_flatten(Mat &I, Mat &final); + void texture_flatten(Mat &I, Mat &mask, Mat &wmask, Mat &final); }; void Cloning::getGradientx( const Mat &img, Mat &gx) @@ -782,91 +782,79 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alph } } -void Cloning::texture_flatten(Mat &I, Mat &final) + +void Cloning::texture_flatten(Mat &I, Mat &mask, Mat &wmask, Mat &final) { + init(I,wmask); - grx = Mat(I.size(),CV_32FC3); - gry = Mat(I.size(),CV_32FC3); + int w = I.size().width; + int h = I.size().height; - Mat out = Mat(I.size(),CV_8UC1); + getGradientx(I,grx); + getGradienty(I,gry); - getGradientx( I, grx); - getGradienty( I, gry); + getGradientx(mask,sgx); + getGradienty(mask,sgy); - Canny( I, out, 30, 45, 3 ); + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); - int channel = I.channels(); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); - for(int i=0;i(i,j) != 255) { - grx.at(i,j*channel+c) = 0.0; - gry.at(i,j*channel+c) = 0.0; + sgx.at(i,j*channel+c) = 0.0; + sgy.at(i,j*channel+c) = 0.0; } } - r_channel = Mat::zeros(I.size(),CV_8UC1); - g_channel = Mat::zeros(I.size(),CV_8UC1); - b_channel = Mat::zeros(I.size(),CV_8UC1); + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } - for(int i=0;i(i,j) = I.at(i,j*3+0); - g_channel.at(i,j) = I.at(i,j*3+1); - b_channel.at(i,j) = I.at(i,j*3+2); - } + bitwise_not(wmask,wmask); - Mat gxx = Mat(I.size(),CV_32FC3); - Mat gyy = Mat(I.size(),CV_32FC3); + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); - lapx(grx,gxx); - lapy(gry,gyy); + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } - rx_channel = Mat(I.size(),CV_32FC1); - gx_channel = Mat(I.size(),CV_32FC1); - bx_channel = Mat(I.size(),CV_32FC1); + calc(I,grx32,gry32,srx32,sry32); - for(int i=0;i(i,j) = gxx.at(i,j*3+0); - gx_channel.at(i,j) = gxx.at(i,j*3+1); - bx_channel.at(i,j) = gxx.at(i,j*3+2); - } - - ry_channel = Mat(I.size(),CV_32FC1); - gy_channel = Mat(I.size(),CV_32FC1); - by_channel = Mat(I.size(),CV_32FC1); - - for(int i=0;i(i,j) = gyy.at(i,j*3+0); - gy_channel.at(i,j) = gyy.at(i,j*3+1); - by_channel.at(i,j) = gyy.at(i,j*3+2); - } - - resultr = Mat(I.size(),CV_8UC1); - resultg = Mat(I.size(),CV_8UC1); - resultb = Mat(I.size(),CV_8UC1); - - clock_t tic = clock(); - - - poisson_solver(r_channel,rx_channel, ry_channel,resultr); - poisson_solver(g_channel,gx_channel, gy_channel,resultg); - poisson_solver(b_channel,bx_channel, by_channel,resultb); - - clock_t toc = clock(); - - printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); - - for(int i=0;i(i,j*3+0) = resultr.at(i,j); final.at(i,j*3+1) = resultg.at(i,j); diff --git a/modules/photo/test/test_cloning.cpp b/modules/photo/test/test_cloning.cpp index 583a069aee..bb62d874aa 100644 --- a/modules/photo/test/test_cloning.cpp +++ b/modules/photo/test/test_cloning.cpp @@ -164,14 +164,17 @@ TEST(Photo_SeamlessClone_illuminationChange, regression) TEST(Photo_SeamlessClone_textureFlattening, regression) { string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Texture_Flattening/"; - string original_path = folder + "source1.png"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; - Mat source = imread(original_path, IMREAD_COLOR); + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); - ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path; + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1; + ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2; Mat result; - textureFlattening(source, result); + textureFlattening(source, mask, result); imwrite(folder + "cloned.png", result); diff --git a/samples/cpp/cloning.cpp b/samples/cpp/cloning.cpp index 70725d8e74..9a41ce229b 100644 --- a/samples/cpp/cloning.cpp +++ b/samples/cpp/cloning.cpp @@ -6,26 +6,31 @@ * * This tutorial demonstrates how to use OpenCV seamless cloning * module. -* Flags: -* 1- NORMAL_CLONE -* 2- MIXED_CLONE -* 3- FEATURE_EXCHANGE +* +* 1- Normal Cloning +* 2- Mixed Cloning +* 3- Monochrome Transfer +* 4- Color Change +* 5- Illumination change +* 6- Texture Flattening -* The program takes as input a source and a destination image +* The program takes as input a source and a destination image (for 1-3 methods) * and ouputs the cloned image. * Step 1: * -> In the source image, select the region of interest by left click mouse button. A Polygon ROI will be created by left clicking mouse button. -* -> To set the Polygon ROI, click the right mouse button. -* -> To reset the region selected, click the middle mouse button. +* -> To set the Polygon ROI, click the right mouse button or 'd' key. +* -> To reset the region selected, click the middle mouse button or 'r' key. * Step 2: * -> In the destination image, select the point where you want to place the ROI in the image by left clicking mouse button. -* -> To get the cloned result, click the right mouse button. - +* -> To get the cloned result, click the right mouse button or 'c' key. +* -> To quit the program, use 'q' key. +* * Result: The cloned image will be displayed. */ +#include #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" @@ -47,6 +52,8 @@ Point* pts = new Point[100]; Point* pts2 = new Point[100]; Point* pts_diff = new Point[100]; +char src[50]; +char dest[50]; int var = 0; int flag = 0; @@ -57,6 +64,10 @@ int minxd,minyd,maxxd,maxyd,lenxd,lenyd; int channel,num; +float alpha,beta; + +float red, green, blue; + void source(int event, int x, int y, int, void*) { @@ -93,20 +104,20 @@ void source(int event, int x, int y, int, void*) pts[i] = point; if(var!=0) - { - const Point* pts3[1] = {&pts[0]}; - polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); - } + { + const Point* pts3[1] = {&pts[0]}; + polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); + } - for(int i=0;i im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0) - { - cout << "Index out of range" << endl; - exit(0); - } + if(maxxd > im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0) + { + cout << "Index out of range" << endl; + exit(0); + } - final1 = Mat::zeros(img2.size(),CV_8UC3); - res = Mat::zeros(img2.size(),CV_8UC1); - for(int i=miny, k=minyd;i<(miny+leny);i++,k++) - for(int j=minx,l=minxd ;j<(minx+lenx);j++,l++) - { - for(int c=0;c(k,l*channel+c) = final.at(i,j*channel+c); + final1 = Mat::zeros(img2.size(),CV_8UC3); + res = Mat::zeros(img2.size(),CV_8UC1); + for(int i=miny, k=minyd;i<(miny+leny);i++,k++) + for(int j=minx,l=minxd ;j<(minx+lenx);j++,l++) + { + for(int c=0;c(k,l*channel+c) = final.at(i,j*channel+c); - } - } + } + } - const Point* pts6[1] = {&pts2[0]}; - fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0); + const Point* pts6[1] = {&pts2[0]}; + fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0); - if(num == 1 || num == 2 || num == 3) - { + if(num == 1 || num == 2 || num == 3) + { seamlessClone(img0,img2,res1,point,blend,num); - imshow("Cloned Image", blend); + imshow("Cloned Image", blend); imwrite("cloned.png",blend); - waitKey(0); - } + waitKey(0); + } - for(int i = 0; i < flag ; i++) - { - pts2[i].x=0; - pts2[i].y=0; - } + for(int i = 0; i < flag ; i++) + { + pts2[i].x=0; + pts2[i].y=0; + } - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; - } + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + } - im1.release(); + im1.release(); +} + +void checkfile(char *file) +{ + while(1) + { + printf("Enter %s Image: ",file); + if(!strcmp(file,"Source")) + { + cin >> src; + if(access( src, F_OK ) != -1 ) + { + break; + } + else + { + printf("Image doesn't exist\n"); + } + } + else if(!strcmp(file,"Destination")) + { + cin >> dest; + + if(access( dest, F_OK ) != -1 ) + { + break; + } + else + { + printf("Image doesn't exist\n"); + } + + } + } } int main(int argc, char **argv) { + cout << endl; + cout << "Cloning Module" << endl; + cout << "---------------" << endl; + cout << "Step 1:" << endl; + cout << " -> In the source image, select the region of interest by left click mouse button. A Polygon ROI will be created by left clicking mouse button." << endl; + cout << " -> To set the Polygon ROI, click the right mouse button or use 'd' key" << endl; + cout << " -> To reset the region selected, click the middle mouse button or use 'r' key." << endl; - if (argc != 3) + cout << "Step 2:" << endl; + cout << " -> In the destination image, select the point where you want to place the ROI in the image by left clicking mouse button." << endl; + cout << " -> To get the cloned result, click the right mouse button or use 'c' key." << endl; + cout << " -> To quit the program, use 'q' key." << endl; + cout << endl; + cout << "Options: " << endl; + cout << endl; + cout << "1) Normal Cloning " << endl; + cout << "2) Mixed Cloning " << endl; + cout << "3) Monochrome Transfer " << endl; + cout << "4) Local Color Change " << endl; + cout << "5) Local Illumination Change " << endl; + cout << "6) Texture Flattening " << endl; + + cout << endl; + + cout << "Press number 1-6 to choose from above techniques: "; + cin >> num; + cout << endl; + + char s[]="Source"; + char d[]="Destination"; + + minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + + if(num == 1 || num == 2 || num == 3) { - cout << "usage: " << argv[0] << " " << " " << endl; - exit(1); + + checkfile(s); + checkfile(d); + + img0 = imread(src); + + img2 = imread(dest); + + channel = img0.channels(); + + res = Mat::zeros(img2.size(),CV_8UC1); + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + final1 = Mat::zeros(img2.size(),CV_8UC3); + //////////// source image /////////////////// + + namedWindow("Source", 1); + setMouseCallback("Source", source, NULL); + imshow("Source", img0); + + /////////// destination image /////////////// + + namedWindow("Destination", 1); + setMouseCallback("Destination", destination, NULL); + imshow("Destination",img2); + + } + else if(num == 4) + { + checkfile(s); + + cout << "Enter RGB values: " << endl; + cout << "Red: "; + cin >> red; + + cout << "Green: "; + cin >> green; + + cout << "Blue: "; + cin >> blue; + + img0 = imread(src); + + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + + + //////////// source image /////////////////// + + namedWindow("Source", 1); + setMouseCallback("Source", source, NULL); + imshow("Source", img0); + + + } + else if(num == 5) + { + checkfile(s); + + cout << "alpha: "; + cin >> alpha; + + cout << "beta: "; + cin >> beta; + + img0 = imread(src); + + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + + //////////// source image /////////////////// + + namedWindow("Source", 1); + setMouseCallback("Source", source, NULL); + imshow("Source", img0); + + + } + else if(num == 6) + { + checkfile(s); + + img0 = imread(src); + + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + + //////////// source image /////////////////// + + namedWindow("Source", 1); + setMouseCallback("Source", source, NULL); + imshow("Source", img0); + } + + while(true) + { + char key = waitKey(0); + + if(key == 'd') + { + flag1 = 1; + img1 = img0.clone(); + for(int i = var; i < numpts ; i++) + pts[i] = point; + + if(var!=0) + { + const Point* pts3[1] = {&pts[0]}; + polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); + } + + for(int i=0;i> num; - - minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; - - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; - - img0 = src; - img2 = dest; - - channel = img0.channels(); - - res = Mat::zeros(img2.size(),CV_8UC1); - res1 = Mat::zeros(img0.size(),CV_8UC1); - final = Mat::zeros(img0.size(),CV_8UC3); - final1 = Mat::zeros(img2.size(),CV_8UC3); - //////////// source image /////////////////// - - namedWindow("Source", 1); - setMouseCallback("Source", source, NULL); - imshow("Source", img0); - - /////////// destination image /////////////// - - namedWindow("Destination", 1); - setMouseCallback("Destination", destination, NULL); - imshow("Destination",img2); - waitKey(0); - - img0.release(); - img1.release(); - img2.release(); + waitKey(0); } From ae9b4003ae932f98050086ef69a29884a031d8d1 Mon Sep 17 00:00:00 2001 From: siddharth Date: Tue, 27 Aug 2013 13:38:38 +0530 Subject: [PATCH 23/97] edge preserve filters added and windows warning removed update1 --- modules/photo/src/npr.cpp | 34 +++ modules/photo/src/npr.hpp | 490 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 524 insertions(+) create mode 100644 modules/photo/src/npr.cpp create mode 100644 modules/photo/src/npr.hpp diff --git a/modules/photo/src/npr.cpp b/modules/photo/src/npr.cpp new file mode 100644 index 0000000000..c2311c8122 --- /dev/null +++ b/modules/photo/src/npr.cpp @@ -0,0 +1,34 @@ +#include "precomp.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" +#include +#include + +#include "npr.hpp" + +using namespace std; +using namespace cv; + +void cv::edgepreservefilter(InputArray _src, OutputArray _dst, int flags, float sigma_s, float sigma_r) +{ + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC3); + Mat dst = _dst.getMat(); + + int h = I.size().height; + int w = I.size().width; + + Mat res = Mat(h,w,CV_32FC3); + dst.convertTo(res,CV_32FC3,1.0/255.0); + + Domain_Filter obj; + + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + + obj.filter(img, res, sigma_s, sigma_r, flags); + + convertScaleAbs(res, dst, 255,0); +} diff --git a/modules/photo/src/npr.hpp b/modules/photo/src/npr.hpp new file mode 100644 index 0000000000..856a4768b6 --- /dev/null +++ b/modules/photo/src/npr.hpp @@ -0,0 +1,490 @@ +#include "precomp.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include +#include +#include +#include "math.h" + +using namespace std; +using namespace cv; + +double myinf = std::numeric_limits::infinity(); + +class Domain_Filter +{ + public: + Mat ct_H, ct_V, horiz, vert, O, O_t, lower_idx, upper_idx; + void init(const Mat &img, int flags, float sigma_s, float sigma_r); + void getGradientx( const Mat &img, Mat &gx); + void getGradienty( const Mat &img, Mat &gy); + void diffx(const Mat &img, Mat &temp); + void diffy(const Mat &img, Mat &temp); + void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius); + void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h); + void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius); + void filter(const Mat &img, Mat &res, float sigma_s, float sigma_r, int flags); +}; + +void Domain_Filter::diffx(const Mat &img, Mat &temp) +{ + int channel = img.channels(); + + for(int i = 0; i < img.size().height; i++) + for(int j = 0; j < img.size().width-1; j++) + { + for(int c =0; c < channel; c++) + { + temp.at(i,j*channel+c) = + img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); + } + } +} + +void Domain_Filter::diffy(const Mat &img, Mat &temp) +{ + int channel = img.channels(); + + for(int i = 0; i < img.size().height-1; i++) + for(int j = 0; j < img.size().width; j++) + { + for(int c =0; c < channel; c++) + { + temp.at(i,j*channel+c) = + img.at((i+1),j*channel+c) - img.at(i,j*channel+c); + } + } +} + +void Domain_Filter::getGradientx( const Mat &img, Mat &gx) +{ + int w = img.cols; + int h = img.rows; + int channel = img.channels(); + + for(int i=0;i(i,j*channel+c) = + img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); + } +} +void Domain_Filter::getGradienty( const Mat &img, Mat &gy) +{ + int w = img.cols; + int h = img.rows; + int channel = img.channels(); + + for(int i=0;i(i,j*channel+c) = + img.at(i+1,j*channel+c) - img.at(i,j*channel+c); + + } +} + +void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) +{ + + float a; + + int h = output.rows; + int w = output.cols; + int channel = output.channels(); + + a = exp(-sqrt(2) / sigma_h); + + Mat temp = Mat(h,w,CV_32FC3); + + for(int i =0; i < h;i++) + for(int j=0;j(i,j*channel+c) = output.at(i,j*channel+c); + + + Mat V = Mat(h,w,CV_32FC1); + + for(int i=0;i(i,j) = pow(a,hz.at(i,j)); + + + for(int i=0; i(i,j*channel+c) = temp.at(i,j*channel+c) + + (temp.at(i,(j-1)*channel+c) - temp.at(i,j*channel+c)) * V.at(i,j); + } + } + } + + for(int i=0; i= 0; j--) + { + for(int c = 0; c(i,j*channel+c) = temp.at(i,j*channel+c) + + (temp.at(i,(j+1)*channel+c) - temp.at(i,j*channel+c))*V.at(i,j+1); + } + } + } + + + for(int i =0; i < h;i++) + for(int j=0;j(i,j*channel+c) = temp.at(i,j*channel+c); + + temp.release(); + V.release(); + + +} + +void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius) +{ + int h = output.rows; + int w = output.cols; + Mat lower_pos = Mat(h,w,CV_32FC1); + Mat upper_pos = Mat(h,w,CV_32FC1); + + for(int i=0;i(i,j) = hz.at(i,j) - radius; + upper_pos.at(i,j) = hz.at(i,j) + radius; + } + + lower_idx = Mat::zeros(h,w,CV_32FC1); + upper_idx = Mat::zeros(h,w,CV_32FC1); + + Mat domain_row = Mat::zeros(1,w+1,CV_32FC1); + + for(int i=0;i(0,j) = hz.at(i,j); + domain_row.at(0,w) = myinf; + + Mat lower_pos_row = Mat::zeros(1,w,CV_32FC1); + Mat upper_pos_row = Mat::zeros(1,w,CV_32FC1); + + for(int j=0;j(0,j) = lower_pos.at(i,j); + upper_pos_row.at(0,j) = upper_pos.at(i,j); + } + + Mat temp_lower_idx = Mat::zeros(1,w,CV_32FC1); + Mat temp_upper_idx = Mat::zeros(1,w,CV_32FC1); + + for(int j=0;j(0,j) > lower_pos_row.at(0,0)) + { + temp_lower_idx.at(0,0) = j; + break; + } + } + for(int j=0;j(0,j) > upper_pos_row.at(0,0)) + { + temp_upper_idx.at(0,0) = j; + break; + } + } + + int temp = 0; + for(int j=1;j(0,j-1);k(0,k) > lower_pos_row.at(0,j)) + { + temp = count; + break; + } + count++; + } + + temp_lower_idx.at(0,j) = temp_lower_idx.at(0,j-1) + temp; + + count = 0; + for(int k=temp_upper_idx.at(0,j-1);k(0,k) > upper_pos_row.at(0,j)) + { + temp = count; + break; + } + count++; + } + + temp_upper_idx.at(0,j) = temp_upper_idx.at(0,j-1) + temp; + } + + for(int j=0;j(i,j) = temp_lower_idx.at(0,j) + 1; + upper_idx.at(i,j) = temp_upper_idx.at(0,j) + 1; + } + + + lower_pos_row.release(); + upper_pos_row.release(); + temp_lower_idx.release(); + temp_upper_idx.release(); + } + for(int i=0;i(i,j) = upper_idx.at(i,j) - lower_idx.at(i,j); + +} +void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float radius) +{ + + int h = output.rows; + int w = output.cols; + int channel = output.channels(); + + compute_boxfilter(output,hz,psketch,radius); + + Mat box_filter = Mat::zeros(h,w+1,CV_32FC3); + + for(int i = 0; i < h; i++) + { + box_filter.at(i,1*channel+0) = output.at(i,0*channel+0); + box_filter.at(i,1*channel+1) = output.at(i,0*channel+1); + box_filter.at(i,1*channel+2) = output.at(i,0*channel+2); + for(int j = 2; j < w+1; j++) + { + for(int c=0;c(i,j*channel+c) = output.at(i,(j-1)*channel+c) + box_filter.at(i,(j-1)*channel+c); + } + } + + Mat indices = Mat::zeros(h,w,CV_32FC1); + Mat final = Mat::zeros(h,w,CV_32FC3); + + for(int i=0;i(i,j) = i+1; + + Mat a = Mat::zeros(h,w,CV_32FC1); + Mat b = Mat::zeros(h,w,CV_32FC1); + + for(int c=0;c(i,j) = (c+1)*flag.at(i,j); + + for(int i=0;i(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (lower_idx.at(i,j) - 1) * h + indices.at(i,j); + b.at(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (upper_idx.at(i,j) - 1) * h + indices.at(i,j); + + } + + int p,q,r,rem; + int p1,q1,r1,rem1; + + for(int i=0;i(i,j)/(h*(w+1)); + rem = b.at(i,j) - r*h*(w+1); + q = rem/h; + p = rem - q*h; + if(q==0) + { + p=h; + q=w; + r=r-1; + } + if(p==0) + { + p=h; + q=q-1; + } + + + r1 = a.at(i,j)/(h*(w+1)); + rem1 = a.at(i,j) - r1*h*(w+1); + q1 = rem1/h; + p1 = rem1 - q1*h; + if(p1==0) + { + p1=h; + q1=q1-1; + } + + + final.at(i,j*channel+2-c) = (box_filter.at(p-1,q*channel+(2-r)) - box_filter.at(p1-1,q1*channel+(2-r1))) + /(upper_idx.at(i,j) - lower_idx.at(i,j)); + } + } + } + + for(int i=0;i(i,j*channel+c) = final.at(i,j*channel+c); + + +} +void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r) +{ + int h = img.size().height; + int w = img.size().width; + int channel = img.channels(); + + //////////////////////////////////// horizontal and vertical partial derivatives ///////////////////////////////// + + Mat derivx = Mat::zeros(h,w-1,CV_32FC3); + Mat derivy = Mat::zeros(h-1,w,CV_32FC3); + + diffx(img,derivx); + diffy(img,derivy); + + Mat distx = Mat::zeros(h,w,CV_32FC1); + Mat disty = Mat::zeros(h,w,CV_32FC1); + + //////////////////////// Compute the l1-norm distance of neighbor pixels //////////////////////////////////////////////// + + for(int i = 0; i < h; i++) + for(int j = 0,k=1; j < w-1; j++,k++) + for(int c = 0; c < channel; c++) + { + distx.at(i,k) = + distx.at(i,k) + abs(derivx.at(i,j*channel+c)); + } + + for(int i = 0,k=1; i < h-1; i++,k++) + for(int j = 0; j < w; j++) + for(int c = 0; c < channel; c++) + { + disty.at(k,j) = + disty.at(k,j) + abs(derivy.at(i,j*channel+c)); + } + + ////////////////////// Compute the derivatives of the horizontal and vertical domain transforms. ///////////////////////////// + + horiz = Mat(h,w,CV_32FC1); + vert = Mat(h,w,CV_32FC1); + + Mat final = Mat(h,w,CV_32FC3); + + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + { + horiz.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * distx.at(i,j); + vert.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * disty.at(i,j); + } + + + O = Mat(h,w,CV_32FC3); + + for(int i =0;i(i,j*channel+c) = img.at(i,j*channel+c); + + O_t = Mat(w,h,CV_32FC3); + + if(flags == 2) + { + + ct_H = Mat(h,w,CV_32FC1); + ct_V = Mat(h,w,CV_32FC1); + + for(int i = 0; i < h; i++) + { + ct_H.at(i,0) = horiz.at(i,0); + for(int j = 1; j < w; j++) + { + ct_H.at(i,j) = horiz.at(i,j) + ct_H.at(i,j-1); + } + } + + for(int j = 0; j < w; j++) + { + ct_V.at(0,j) = vert.at(0,j); + for(int i = 1; i < h; i++) + { + ct_V.at(i,j) = vert.at(i,j) + ct_V.at(i-1,j); + } + } + } + +} +void Domain_Filter::filter(const Mat &img, Mat &res, float sigma_s = 60, float sigma_r = 0.4, int flags = 1) +{ + int no_of_iter = 3; + int h = img.size().height; + int w = img.size().width; + float sigma_h = sigma_s; + + init(img,flags,sigma_s,sigma_r); + + if(flags == 1) + { + + Mat vert_t = vert.t(); + + for(int i=0;i Date: Tue, 3 Sep 2013 21:12:05 +0530 Subject: [PATCH 24/97] new filters added and all the 3 modules updated All 3 modules Updated --- modules/photo/doc/cloning.rst | 27 +- modules/photo/doc/npr.rst | 90 +++ modules/photo/include/opencv2/photo.hpp | 34 +- modules/photo/src/contrast_preserve.cpp | 240 ++++--- modules/photo/src/contrast_preserve.hpp | 30 +- modules/photo/src/npr.cpp | 236 ++++++- modules/photo/src/npr.hpp | 883 ++++++++++++++---------- modules/photo/src/seamless_cloning.cpp | 58 +- modules/photo/src/seamless_cloning.hpp | 30 +- modules/photo/test/test_cloning.cpp | 4 +- modules/photo/test/test_npr.cpp | 146 ++++ samples/cpp/cloning.cpp | 42 +- samples/cpp/cloning_example.cpp | 243 +++++++ samples/cpp/npr_demo.cpp | 107 +++ 14 files changed, 1600 insertions(+), 570 deletions(-) create mode 100644 modules/photo/doc/npr.rst create mode 100644 modules/photo/test/test_npr.cpp create mode 100644 samples/cpp/cloning_example.cpp create mode 100644 samples/cpp/npr_demo.cpp diff --git a/modules/photo/doc/cloning.rst b/modules/photo/doc/cloning.rst index 740e1ab64b..11e9bce135 100644 --- a/modules/photo/doc/cloning.rst +++ b/modules/photo/doc/cloning.rst @@ -39,19 +39,21 @@ colorChange ----------- Given an original color image, two differently colored versions of this image can be mixed seamlessly. -.. ocv:function:: void colorChange( InputArray src, OutputArray dst, float red = 1.0, float green = 1.0, float blue = 1.0) +.. ocv:function:: void colorChange( InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, float green_mul = 1.0, float blue_mul = 1.0) :param src: Input 8-bit 3-channel image. + :param mask: Input 8-bit 1 or 3-channel image. + :param dst: Output image with the same size and type as ``src`` . - :param red: R-channel Value + :param red_mul: R-channel multiply factor. - :param green: G-channel Value + :param green_mul: G-channel multiply factor. - :param blue: B-channel Value + :param blue_mul: B-channel multiply factor. -RGB values between .5 to 2.5 +Multiplication factor is between .5 to 2.5. illuminationChange @@ -59,10 +61,12 @@ illuminationChange Applying an appropriate non-linear transformation to the gradient field inside the selection and then integrating back with a Poisson solver, modifies locally the apparent illumination of an image. -.. ocv:function:: void illuminationChange(InputArray src, OutputArray dst, float alpha = 0.2, float beta = 0.4) +.. ocv:function:: void illuminationChange(InputArray src, InputArray mask, OutputArray dst, float alpha = 0.2, float beta = 0.4) :param src: Input 8-bit 3-channel image. + :param mask: Input 8-bit 1 or 3-channel image. + :param dst: Output image with the same size and type as ``src``. :param alpha: Value ranges between 0-2. @@ -74,14 +78,21 @@ This is useful to highlight under-exposed foreground objects or to reduce specul textureFlattening ----------------- By retaining only the gradients at edge locations, before integrating with the Poisson solver, one washes out the texture of the selected -region, giving its contents a flat aspect. +region, giving its contents a flat aspect. Here Canny Edge Detector is used. -.. ocv:function:: void textureFlattening(InputArray src, OutputArray dst) +.. ocv:function:: void textureFlattening(InputArray src, InputArray mask, OutputArray dst, double low_threshold, double high_threshold, int kernel_size) :param src: Input 8-bit 3-channel image. + :param mask: Input 8-bit 1 or 3-channel image. + :param dst: Output image with the same size and type as ``src``. + :param low_threshold: Range from 0 to 100. + + :param high_threshold: Value > 100. + + :param kernel_size: The size of the Sobel kernel to be used. **NOTE:** diff --git a/modules/photo/doc/npr.rst b/modules/photo/doc/npr.rst new file mode 100644 index 0000000000..db56c6955c --- /dev/null +++ b/modules/photo/doc/npr.rst @@ -0,0 +1,90 @@ +Non-Photorealistic Rendering +============================ + +.. highlight:: cpp + +edgePreservingFilter +-------------------- + +Filtering is the fundamental operation in image and video processing. Edge-preserving smoothing filters are used in many different applications. + +.. ocv:function:: void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4); + + :param src: Input 8-bit 3-channel image. + + :param dst: Output 8-bit 3-channel image. + + :param flags: Edge preserving filters: + + * **RECURS_FILTER** + + * **NORMCONV_FILTER** + + :param sigma_s: Range between 0 to 200. + + :param sigma_r: Range between 0 to 1. + + +detailEnhance +------------- +This filter enhances the details of a particular image. + +.. ocv:function:: void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, float sigma_r = 0.15); + + :param src: Input 8-bit 3-channel image. + + :param dst: Output image with the same size and type as ``src``. + + :param sigma_s: Range between 0 to 200. + + :param sigma_r: Range between 0 to 1. + + +pencilSketch +------------ +Pencil-like non-photorealistic line drawing + +.. ocv:function:: void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); + + :param src: Input 8-bit 3-channel image. + + :param dst1: Output 8-bit 1-channel image. + + :param dst2: Output image with the same size and type as ``src``. + + :param sigma_s: Range between 0 to 200. + + :param sigma_r: Range between 0 to 1. + + :param shade_factor: Range between 0 to 0.1. + + +stylization +----------- +Stylization aims to produce digital imagery with a wide variety of effects not focused on photorealism. Edge-aware filters are ideal for stylization, as they can abstract regions of low contrast while preserving, or enhancing, high-contrast features. + +.. ocv:function:: void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45); + + :param src: Input 8-bit 3-channel image. + + :param dst: Output image with the same size and type as ``src``. + + :param sigma_s: Range between 0 to 200. + + :param sigma_r: Range between 0 to 1. + + +edgeEnhance +----------- +Able to suppress low-amplitude details and enhance edges. + +.. ocv:function:: void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45); + + :param src: Input 8-bit 3-channel image. + + :param dst: Output 8-bit 1-channel image. + + :param sigma_s: Range between 0 to 200. + + :param sigma_r: Range between 0 to 1. + diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index d825c2489e..1eb5ccaab1 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -68,8 +68,8 @@ enum enum { - RECURSIVE_FILTER = 1, - NC_FILTER = 2 + RECURS_FILTER = 1, + NORMCONV_FILTER = 2 }; //! restores the damaged image areas using one of the available intpainting algorithms @@ -301,17 +301,35 @@ public: CV_EXPORTS_W Ptr createMergeRobertson(); -CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost); +CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost); -CV_EXPORTS_W void seamlessClone(InputArray src, InputArray dst, InputArray mask, Point p, OutputArray _blend, int flags); +CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, + OutputArray _blend, int flags); -CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red = 1.0, float green = 1.0, float blue = 1.0); +CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, + float green_mul = 1.0, float blue_mul = 1.0); -CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, float alpha = 0.2, float beta = 0.4); +CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, + float alpha = 0.2, float beta = 0.4); -CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst); +CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, + double low_threshold, double high_threshold, + int kernel_size); -CV_EXPORTS_W void edgepreservefilter(InputArray _src, OutputArray _dst, int flags = 1, float sigma_h = 60, float sigma_r = 0.4); +CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, + float sigma_s = 60, float sigma_r = 0.4); + +CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, + float sigma_r = 0.15); + +CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst, OutputArray dst1, + float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); + +CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, + float sigma_r = 0.45); + +CV_EXPORTS_W void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, + float sigma_r = 0.45); } // cv diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 9a659691a8..14ed6ac30f 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -57,7 +57,7 @@ double norm(double); double norm(double E) { - return (sqrt(pow(E,2))); + return (sqrt(pow(E,2))); } void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) @@ -71,170 +71,168 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) if(!I.data ) { - cout << "Could not open or find the image" << endl ; - return; - } - if(I.channels() !=3) - { - cout << "Input Color Image" << endl; - return; - } + cout << "Could not open or find the image" << endl ; + return; + } + if(I.channels() !=3) + { + cout << "Input Color Image" << endl; + return; + } - int maxIter = 15; - int iterCount = 0; + int maxIter = 15; + int iterCount = 0; float tol = .0001; double E = 0; double pre_E = std::numeric_limits::infinity(); - Decolor obj; + Decolor obj; - Mat img; + Mat img; img = Mat(I.size(),CV_32FC3); I.convertTo(img,CV_32FC3,1.0/255.0); obj.init(); - vector Cg; - vector < vector > polyGrad; - vector < vector > bc; - vector < vector < int > > comb; + vector Cg; + vector < vector > polyGrad; + vector < vector > bc; + vector < vector < int > > comb; - vector alf; + vector alf; - obj.grad_system(img,polyGrad,Cg,comb); - obj.weak_order(img,alf); + obj.grad_system(img,polyGrad,Cg,comb); + obj.weak_order(img,alf); - Mat Mt = Mat(polyGrad.size(),polyGrad[0].size(), CV_32FC1); - obj.wei_update_matrix(polyGrad,Cg,Mt); + Mat Mt = Mat(polyGrad.size(),polyGrad[0].size(), CV_32FC1); + obj.wei_update_matrix(polyGrad,Cg,Mt); - vector wei; - obj.wei_inti(comb,wei); + vector wei; + obj.wei_inti(comb,wei); - //////////////////////////////// main loop starting //////////////////////////////////////// + //////////////////////////////// main loop starting //////////////////////////////////////// - while(norm(E-pre_E) > tol) - { - iterCount +=1; + while(norm(E-pre_E) > tol) + { + iterCount +=1; pre_E = E; - vector G_pos; - vector G_neg; + vector G_pos; + vector G_neg; - vector temp; - vector temp1; + vector temp; + vector temp1; - double val = 0.0; - for(unsigned int i=0;i< polyGrad[0].size();i++) - { - val = 0.0; - for(unsigned int j =0;j EXPsum; - vector EXPterm; + vector EXPsum; + vector EXPterm; - for(unsigned int i = 0;i temp2; - vector temp2; + for(unsigned int i=0;i wei1; - - double val1 = 0.0; - vector wei1; + for(unsigned int i=0;i< polyGrad.size();i++) + { + val1 = 0.0; + for(unsigned int j =0;j(i,j) * EXPterm[j]); + } + wei1.push_back(val1); + } - for(unsigned int i=0;i< polyGrad.size();i++) - { - val1 = 0.0; - for(unsigned int j =0;j(i,j) * EXPterm[j]); - } - wei1.push_back(val1); - } - - for(unsigned int i =0;i maxIter) break; - G_pos.clear(); - G_neg.clear(); - temp.clear(); - temp1.clear(); - EXPsum.clear(); - EXPterm.clear(); - temp2.clear(); - wei1.clear(); - } + G_pos.clear(); + G_neg.clear(); + temp.clear(); + temp1.clear(); + EXPsum.clear(); + EXPterm.clear(); + temp2.clear(); + wei1.clear(); + } - Mat Gray = Mat::zeros(img.size(),CV_32FC1); - obj.grayImContruct(wei, img, Gray); + Mat Gray = Mat::zeros(img.size(),CV_32FC1); + obj.grayImContruct(wei, img, Gray); - Gray.convertTo(dst,CV_8UC1,255); + Gray.convertTo(dst,CV_8UC1,255); /////////////////////////////////// Contrast Boosting ///////////////////////////////// - - Mat lab = Mat(img.size(),CV_8UC3); - Mat color = Mat(img.size(),CV_8UC3); - Mat l = Mat(img.size(),CV_8UC1); - Mat a = Mat(img.size(),CV_8UC1); - Mat b = Mat(img.size(),CV_8UC1); - cvtColor(I,lab,COLOR_BGR2Lab); + Mat lab = Mat(img.size(),CV_8UC3); + Mat color = Mat(img.size(),CV_8UC3); + Mat l = Mat(img.size(),CV_8UC1); + Mat a = Mat(img.size(),CV_8UC1); + Mat b = Mat(img.size(),CV_8UC1); - int h1 = img.size().height; - int w1 = img.size().width; + cvtColor(I,lab,COLOR_BGR2Lab); - for(int i =0;i(i,j) = lab.at(i,j*3+0); - a.at(i,j) = lab.at(i,j*3+1); - b.at(i,j) = lab.at(i,j*3+2); - } - - for(int i =0;i(i,j) = 255.0*Gray.at(i,j); - } + int h1 = img.size().height; + int w1 = img.size().width; - for(int i =0;i(i,j*3+0) = l.at(i,j); - lab.at(i,j*3+1) = a.at(i,j); - lab.at(i,j*3+2) = b.at(i,j); - } + for(int i =0;i(i,j) = lab.at(i,j*3+0); + a.at(i,j) = lab.at(i,j*3+1); + b.at(i,j) = lab.at(i,j*3+2); + } - cvtColor(lab,color_boost,COLOR_Lab2BGR); + for(int i =0;i(i,j) = 255.0*Gray.at(i,j); + } + + for(int i =0;i(i,j*3+0) = l.at(i,j); + lab.at(i,j*3+1) = a.at(i,j); + lab.at(i,j*3+2) = b.at(i,j); + } + + cvtColor(lab,color_boost,COLOR_Lab2BGR); } diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 607b494832..c9d75036c2 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -39,7 +39,6 @@ // //M*/ - #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" @@ -69,7 +68,7 @@ class Decolor void add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad); void weak_order(Mat img, vector &alf); void grad_system(Mat img, vector < vector < double > > &polyGrad, - vector < double > &Cg, vector < vector >& comb); + vector < double > &Cg, vector < vector >& comb); void wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X); void wei_inti(vector < vector > &comb, vector &wei); void grayImContruct(vector &wei, Mat img, Mat &Gray); @@ -87,7 +86,6 @@ float sigma = .02; double Decolor::energyCalcu(vector &Cg, vector < vector > &polyGrad, vector &wei) { vector P; - vector temp; vector temp1; @@ -112,8 +110,6 @@ double Decolor::energyCalcu(vector &Cg, vector < vector > &pol } - - void Decolor::init() { kernel = Mat(1,2, CV_32FC1); @@ -123,7 +119,6 @@ void Decolor::init() kernel1.at(0,0)=1.0; kernel1.at(1,0)=-1.0; order = 2; - } vector Decolor::product(vector < vector > &comb, vector &initRGB) @@ -183,7 +178,7 @@ void Decolor::gradvector(const Mat &img, vector &grad) dest.release(); dest1.release(); } - + void Decolor::colorGrad(Mat img, vector &Cg) { @@ -222,7 +217,6 @@ void Decolor::colorGrad(Mat img, vector &Cg) ImL.clear(); Ima.clear(); Imb.clear(); - } void Decolor::add_vector(vector < vector > &comb, int r,int g,int b) @@ -267,7 +261,7 @@ void Decolor::weak_order(Mat img, vector &alf) green.at(i,j) = img.at(i,j*3+1); blue.at(i,j) = img.at(i,j*3+0); } - + vector Rg; vector Gg; vector Bg; @@ -275,7 +269,7 @@ void Decolor::weak_order(Mat img, vector &alf) vector t1; vector t2; vector t3; - + vector tmp1; vector tmp2; vector tmp3; @@ -333,7 +327,7 @@ void Decolor::weak_order(Mat img, vector &alf) for(unsigned int i =0 ;i < Rg.size();i++) alf[i] -= tmp1[i] * tmp2[i] * tmp3[i]; - + double sum =0.0; for(unsigned int i=0;i &alf) } void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, - vector < double > &Cg, vector < vector >& comb) + vector < double > &Cg, vector < vector >& comb) { int h = img.size().height; int w = img.size().width; - double sizefactor; if((h + w) > 800) { @@ -375,7 +368,7 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, h = img.size().height; w = img.size().width; colorGrad(img,Cg); - + Mat curIm = Mat(img.size(),CV_32FC1); Mat red = Mat(img.size(),CV_32FC1); Mat green = Mat(img.size(),CV_32FC1); @@ -400,7 +393,7 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, for(int j=0;j(i,j)= pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); + pow(blue.at(i,j),b); vector curGrad; gradvector(curIm,curGrad); add_to_vector_poly(polyGrad,curGrad); @@ -468,7 +461,6 @@ void Decolor::wei_inti(vector < vector > &comb, vector &wei) void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) { - int h=img.size().height; int w=img.size().width; @@ -485,7 +477,7 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) } int kk =0; - + for(int r =0;r<=order;r++) for(int g=0;g<=order;g++) for(int b=0;b<=order;b++) @@ -495,7 +487,7 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int j=0;j(i,j)=Gray.at(i,j) + wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); + pow(blue.at(i,j),b); kk=kk+1; } @@ -508,7 +500,7 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) { if(Gray.at(i,j) < minval) minval = Gray.at(i,j); - + if(Gray.at(i,j) > maxval) maxval = Gray.at(i,j); } diff --git a/modules/photo/src/npr.cpp b/modules/photo/src/npr.cpp index c2311c8122..54f5ce55ed 100644 --- a/modules/photo/src/npr.cpp +++ b/modules/photo/src/npr.cpp @@ -1,3 +1,44 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do 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, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/highgui.hpp" @@ -11,7 +52,7 @@ using namespace std; using namespace cv; -void cv::edgepreservefilter(InputArray _src, OutputArray _dst, int flags, float sigma_s, float sigma_r) +void cv::edgePreservingFilter(InputArray _src, OutputArray _dst, int flags, float sigma_s, float sigma_r) { Mat I = _src.getMat(); _dst.create(I.size(), CV_8UC3); @@ -32,3 +73,196 @@ void cv::edgepreservefilter(InputArray _src, OutputArray _dst, int flags, float convertScaleAbs(res, dst, 255,0); } + +void cv::detailEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) +{ + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC3); + Mat dst = _dst.getMat(); + + int h = I.size().height; + int w = I.size().width; + int channel = I.channels(); + float factor = 3.0; + + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + + Mat res = Mat(h,w,CV_32FC3); + dst.convertTo(res,CV_32FC3,1.0/255.0); + + Mat result = Mat(img.size(),CV_32FC3); + Mat lab = Mat(img.size(),CV_32FC3); + Mat l_channel = Mat(img.size(),CV_32FC1); + Mat a_channel = Mat(img.size(),CV_32FC1); + Mat b_channel = Mat(img.size(),CV_32FC1); + + cvtColor(img,lab,COLOR_BGR2Lab); + + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + { + l_channel.at(i,j) = lab.at(i,j*channel+0); + a_channel.at(i,j) = lab.at(i,j*channel+1); + b_channel.at(i,j) = lab.at(i,j*channel+2); + } + + Mat L = Mat(img.size(),CV_32FC1); + + l_channel.convertTo(L,CV_32FC1,1.0/255.0); + + Domain_Filter obj; + + obj.filter(L, res, sigma_s, sigma_r, 1); + + Mat detail = Mat(h,w,CV_32FC1); + + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + detail.at(i,j) = L.at(i,j) - res.at(i,j); + + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + L.at(i,j) = res.at(i,j) + factor*detail.at(i,j); + + L.convertTo(l_channel,CV_32FC1,255); + + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + { + lab.at(i,j*channel+0) = l_channel.at(i,j); + lab.at(i,j*channel+1) = a_channel.at(i,j); + lab.at(i,j*channel+2) = b_channel.at(i,j); + } + + cvtColor(lab,result,COLOR_Lab2BGR); + result.convertTo(dst,CV_8UC3,255); +} + +void cv::pencilSketch(InputArray _src, OutputArray _dst, OutputArray _dst1, float sigma_s, float sigma_r, float shade_factor) +{ + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC1); + Mat dst = _dst.getMat(); + + _dst1.create(I.size(), CV_8UC3); + Mat dst1 = _dst1.getMat(); + + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + + Domain_Filter obj; + + Mat sketch = Mat(I.size(),CV_32FC1); + Mat color_sketch = Mat(I.size(),CV_32FC3); + + obj.pencil_sketch(img, sketch, color_sketch, sigma_s, sigma_r, shade_factor); + + sketch.convertTo(dst,CV_8UC1,255); + color_sketch.convertTo(dst1,CV_8UC3,255); + +} + +void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) +{ + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC3); + Mat dst = _dst.getMat(); + + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + + int h = img.size().height; + int w = img.size().width; + int channel = img.channels(); + + Mat res = Mat(h,w,CV_32FC3); + + Domain_Filter obj; + obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); + + vector planes; + split(res, planes); + + Mat magXR = Mat(h, w, CV_32FC1); + Mat magYR = Mat(h, w, CV_32FC1); + + Mat magXG = Mat(h, w, CV_32FC1); + Mat magYG = Mat(h, w, CV_32FC1); + + Mat magXB = Mat(h, w, CV_32FC1); + Mat magYB = Mat(h, w, CV_32FC1); + + Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); + Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); + + Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); + Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); + + Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); + Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); + + Mat magx = Mat(h,w,CV_32FC1); + Mat magy = Mat(h,w,CV_32FC1); + + Mat mag1 = Mat(h,w,CV_32FC1); + Mat mag2 = Mat(h,w,CV_32FC1); + Mat mag3 = Mat(h,w,CV_32FC1); + + magnitude(magXR,magYR,mag1); + magnitude(magXG,magYG,mag2); + magnitude(magXB,magYB,mag3); + + Mat magnitude = Mat(h,w,CV_32FC1); + + for(int i =0;i < h;i++) + for(int j=0;j(i,j) = mag1.at(i,j) + mag2.at(i,j) + mag3.at(i,j); + } + + for(int i =0;i < h;i++) + for(int j=0;j(i,j) = 1.0 - magnitude.at(i,j); + } + + Mat stylized = Mat(h,w,CV_32FC3); + + for(int i =0;i < h;i++) + for(int j=0;j(i,j*channel + c) = res.at(i,j*channel + c) * magnitude.at(i,j); + } + + stylized.convertTo(dst,CV_8UC3,255); +} + +void cv::edgeEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) +{ + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC1); + Mat dst = _dst.getMat(); + + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + + Mat orig = img.clone(); + + int h = img.size().height; + int w = img.size().width; + + Mat res = Mat(h,w,CV_32FC3); + Mat magnitude = Mat(h,w,CV_32FC1); + + Mat mag8 = Mat(h,w,CV_32FC1); + + Domain_Filter obj; + + obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); + + obj.find_magnitude(res,magnitude); + + magnitude.convertTo(dst,CV_8UC1,255); +} diff --git a/modules/photo/src/npr.hpp b/modules/photo/src/npr.hpp index 856a4768b6..66638ccbd8 100644 --- a/modules/photo/src/npr.hpp +++ b/modules/photo/src/npr.hpp @@ -1,3 +1,44 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do 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, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" @@ -13,478 +54,616 @@ double myinf = std::numeric_limits::infinity(); class Domain_Filter { - public: - Mat ct_H, ct_V, horiz, vert, O, O_t, lower_idx, upper_idx; - void init(const Mat &img, int flags, float sigma_s, float sigma_r); - void getGradientx( const Mat &img, Mat &gx); - void getGradienty( const Mat &img, Mat &gy); - void diffx(const Mat &img, Mat &temp); - void diffy(const Mat &img, Mat &temp); - void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius); - void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h); - void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius); - void filter(const Mat &img, Mat &res, float sigma_s, float sigma_r, int flags); + public: + Mat ct_H, ct_V, horiz, vert, O, O_t, lower_idx, upper_idx; + void init(const Mat &img, int flags, float sigma_s, float sigma_r); + void getGradientx( const Mat &img, Mat &gx); + void getGradienty( const Mat &img, Mat &gy); + void diffx(const Mat &img, Mat &temp); + void diffy(const Mat &img, Mat &temp); + void find_magnitude(Mat &img, Mat &mag); + void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius); + void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h); + void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius); + void filter(const Mat &img, Mat &res, float sigma_s, float sigma_r, int flags); + void pencil_sketch(const Mat &img, Mat &sketch, Mat &color_res, float sigma_s, float sigma_r, float shade_factor); + void Depth_of_field(const Mat &img, Mat &img1, float sigma_s, float sigma_r); }; void Domain_Filter::diffx(const Mat &img, Mat &temp) { - int channel = img.channels(); + int channel = img.channels(); - for(int i = 0; i < img.size().height; i++) - for(int j = 0; j < img.size().width-1; j++) - { - for(int c =0; c < channel; c++) - { - temp.at(i,j*channel+c) = - img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); - } - } + for(int i = 0; i < img.size().height; i++) + for(int j = 0; j < img.size().width-1; j++) + { + for(int c =0; c < channel; c++) + { + temp.at(i,j*channel+c) = + img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); + } + } } void Domain_Filter::diffy(const Mat &img, Mat &temp) { - int channel = img.channels(); + int channel = img.channels(); - for(int i = 0; i < img.size().height-1; i++) - for(int j = 0; j < img.size().width; j++) - { - for(int c =0; c < channel; c++) - { - temp.at(i,j*channel+c) = - img.at((i+1),j*channel+c) - img.at(i,j*channel+c); - } - } + for(int i = 0; i < img.size().height-1; i++) + for(int j = 0; j < img.size().width; j++) + { + for(int c =0; c < channel; c++) + { + temp.at(i,j*channel+c) = + img.at((i+1),j*channel+c) - img.at(i,j*channel+c); + } + } } void Domain_Filter::getGradientx( const Mat &img, Mat &gx) { - int w = img.cols; - int h = img.rows; - int channel = img.channels(); + int w = img.cols; + int h = img.rows; + int channel = img.channels(); - for(int i=0;i(i,j*channel+c) = - img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); - } + for(int i=0;i(i,j*channel+c) = + img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); + } } + void Domain_Filter::getGradienty( const Mat &img, Mat &gy) { - int w = img.cols; - int h = img.rows; - int channel = img.channels(); + int w = img.cols; + int h = img.rows; + int channel = img.channels(); - for(int i=0;i(i,j*channel+c) = - img.at(i+1,j*channel+c) - img.at(i,j*channel+c); + for(int i=0;i(i,j*channel+c) = + img.at(i+1,j*channel+c) - img.at(i,j*channel+c); + + } +} + +void Domain_Filter::find_magnitude(Mat &img, Mat &mag) +{ + + int h = img.rows; + int w = img.cols; + + vector planes; + split(img, planes); + + Mat magXR = Mat(h, w, CV_32FC1); + Mat magYR = Mat(h, w, CV_32FC1); + + Mat magXG = Mat(h, w, CV_32FC1); + Mat magYG = Mat(h, w, CV_32FC1); + + Mat magXB = Mat(h, w, CV_32FC1); + Mat magYB = Mat(h, w, CV_32FC1); + + getGradientx(planes[0], magXR); + getGradienty(planes[0], magYR); + + getGradientx(planes[1], magXG); + getGradienty(planes[1], magYG); + + getGradientx(planes[2], magXR); + getGradienty(planes[2], magYR); + + Mat magx = Mat(h,w,CV_32FC1); + Mat magy = Mat(h,w,CV_32FC1); + + Mat mag1 = Mat(h,w,CV_32FC1); + Mat mag2 = Mat(h,w,CV_32FC1); + Mat mag3 = Mat(h,w,CV_32FC1); + + magnitude(magXR,magYR,mag1); + magnitude(magXG,magYG,mag2); + magnitude(magXB,magYB,mag3); + + for(int i =0;i < h;i++) + for(int j=0;j(i,j) = mag1.at(i,j) + mag2.at(i,j) + mag3.at(i,j); + } + + + for(int i =0;i < h;i++) + for(int j=0;j(i,j) = 1.0 - mag.at(i,j); + } - } } void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) { - float a; + float a; - int h = output.rows; - int w = output.cols; - int channel = output.channels(); + int h = output.rows; + int w = output.cols; + int channel = output.channels(); - a = exp(-sqrt(2) / sigma_h); + a = exp(-sqrt(2) / sigma_h); - Mat temp = Mat(h,w,CV_32FC3); + Mat temp = Mat(h,w,CV_32FC3); - for(int i =0; i < h;i++) - for(int j=0;j(i,j*channel+c) = output.at(i,j*channel+c); + for(int i =0; i < h;i++) + for(int j=0;j(i,j*channel+c) = output.at(i,j*channel+c); - Mat V = Mat(h,w,CV_32FC1); + Mat V = Mat(h,w,CV_32FC1); - for(int i=0;i(i,j) = pow(a,hz.at(i,j)); + for(int i=0;i(i,j) = pow(a,hz.at(i,j)); - for(int i=0; i(i,j*channel+c) = temp.at(i,j*channel+c) + - (temp.at(i,(j-1)*channel+c) - temp.at(i,j*channel+c)) * V.at(i,j); - } - } - } - - for(int i=0; i= 0; j--) - { - for(int c = 0; c(i,j*channel+c) = temp.at(i,j*channel+c) + - (temp.at(i,(j+1)*channel+c) - temp.at(i,j*channel+c))*V.at(i,j+1); - } - } - } + for(int i=0; i(i,j*channel+c) = temp.at(i,j*channel+c) + + (temp.at(i,(j-1)*channel+c) - temp.at(i,j*channel+c)) * V.at(i,j); + } + } + } + + for(int i=0; i= 0; j--) + { + for(int c = 0; c(i,j*channel+c) = temp.at(i,j*channel+c) + + (temp.at(i,(j+1)*channel+c) - temp.at(i,j*channel+c))*V.at(i,j+1); + } + } + } - for(int i =0; i < h;i++) - for(int j=0;j(i,j*channel+c) = temp.at(i,j*channel+c); - - temp.release(); - V.release(); - + for(int i =0; i < h;i++) + for(int j=0;j(i,j*channel+c) = temp.at(i,j*channel+c); + temp.release(); + V.release(); } void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius) { - int h = output.rows; - int w = output.cols; - Mat lower_pos = Mat(h,w,CV_32FC1); - Mat upper_pos = Mat(h,w,CV_32FC1); + int h = output.rows; + int w = output.cols; + Mat lower_pos = Mat(h,w,CV_32FC1); + Mat upper_pos = Mat(h,w,CV_32FC1); - for(int i=0;i(i,j) = hz.at(i,j) - radius; - upper_pos.at(i,j) = hz.at(i,j) + radius; - } + for(int i=0;i(i,j) = hz.at(i,j) - radius; + upper_pos.at(i,j) = hz.at(i,j) + radius; + } - lower_idx = Mat::zeros(h,w,CV_32FC1); - upper_idx = Mat::zeros(h,w,CV_32FC1); + lower_idx = Mat::zeros(h,w,CV_32FC1); + upper_idx = Mat::zeros(h,w,CV_32FC1); - Mat domain_row = Mat::zeros(1,w+1,CV_32FC1); + Mat domain_row = Mat::zeros(1,w+1,CV_32FC1); - for(int i=0;i(0,j) = hz.at(i,j); - domain_row.at(0,w) = myinf; + for(int i=0;i(0,j) = hz.at(i,j); + domain_row.at(0,w) = myinf; - Mat lower_pos_row = Mat::zeros(1,w,CV_32FC1); - Mat upper_pos_row = Mat::zeros(1,w,CV_32FC1); + Mat lower_pos_row = Mat::zeros(1,w,CV_32FC1); + Mat upper_pos_row = Mat::zeros(1,w,CV_32FC1); - for(int j=0;j(0,j) = lower_pos.at(i,j); - upper_pos_row.at(0,j) = upper_pos.at(i,j); - } + for(int j=0;j(0,j) = lower_pos.at(i,j); + upper_pos_row.at(0,j) = upper_pos.at(i,j); + } - Mat temp_lower_idx = Mat::zeros(1,w,CV_32FC1); - Mat temp_upper_idx = Mat::zeros(1,w,CV_32FC1); + Mat temp_lower_idx = Mat::zeros(1,w,CV_32FC1); + Mat temp_upper_idx = Mat::zeros(1,w,CV_32FC1); - for(int j=0;j(0,j) > lower_pos_row.at(0,0)) - { - temp_lower_idx.at(0,0) = j; - break; - } - } - for(int j=0;j(0,j) > upper_pos_row.at(0,0)) - { - temp_upper_idx.at(0,0) = j; - break; - } - } + for(int j=0;j(0,j) > lower_pos_row.at(0,0)) + { + temp_lower_idx.at(0,0) = j; + break; + } + } + for(int j=0;j(0,j) > upper_pos_row.at(0,0)) + { + temp_upper_idx.at(0,0) = j; + break; + } + } - int temp = 0; - for(int j=1;j(0,j-1);k(0,k) > lower_pos_row.at(0,j)) - { - temp = count; - break; - } - count++; - } + int temp = 0; + for(int j=1;j(0,j-1);k(0,k) > lower_pos_row.at(0,j)) + { + temp = count; + break; + } + count++; + } - temp_lower_idx.at(0,j) = temp_lower_idx.at(0,j-1) + temp; + temp_lower_idx.at(0,j) = temp_lower_idx.at(0,j-1) + temp; - count = 0; - for(int k=temp_upper_idx.at(0,j-1);k(0,j-1);k(0,k) > upper_pos_row.at(0,j)) - { - temp = count; - break; - } - count++; - } + if(domain_row.at(0,k) > upper_pos_row.at(0,j)) + { + temp = count; + break; + } + count++; + } - temp_upper_idx.at(0,j) = temp_upper_idx.at(0,j-1) + temp; - } + temp_upper_idx.at(0,j) = temp_upper_idx.at(0,j-1) + temp; + } - for(int j=0;j(i,j) = temp_lower_idx.at(0,j) + 1; - upper_idx.at(i,j) = temp_upper_idx.at(0,j) + 1; - } + for(int j=0;j(i,j) = temp_lower_idx.at(0,j) + 1; + upper_idx.at(i,j) = temp_upper_idx.at(0,j) + 1; + } - - lower_pos_row.release(); - upper_pos_row.release(); - temp_lower_idx.release(); - temp_upper_idx.release(); - } - for(int i=0;i(i,j) = upper_idx.at(i,j) - lower_idx.at(i,j); + lower_pos_row.release(); + upper_pos_row.release(); + temp_lower_idx.release(); + temp_upper_idx.release(); + } + for(int i=0;i(i,j) = upper_idx.at(i,j) - lower_idx.at(i,j); } void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float radius) { - int h = output.rows; - int w = output.cols; - int channel = output.channels(); + int h = output.rows; + int w = output.cols; + int channel = output.channels(); - compute_boxfilter(output,hz,psketch,radius); + compute_boxfilter(output,hz,psketch,radius); - Mat box_filter = Mat::zeros(h,w+1,CV_32FC3); + Mat box_filter = Mat::zeros(h,w+1,CV_32FC3); - for(int i = 0; i < h; i++) - { - box_filter.at(i,1*channel+0) = output.at(i,0*channel+0); - box_filter.at(i,1*channel+1) = output.at(i,0*channel+1); - box_filter.at(i,1*channel+2) = output.at(i,0*channel+2); - for(int j = 2; j < w+1; j++) - { - for(int c=0;c(i,j*channel+c) = output.at(i,(j-1)*channel+c) + box_filter.at(i,(j-1)*channel+c); - } - } + for(int i = 0; i < h; i++) + { + box_filter.at(i,1*channel+0) = output.at(i,0*channel+0); + box_filter.at(i,1*channel+1) = output.at(i,0*channel+1); + box_filter.at(i,1*channel+2) = output.at(i,0*channel+2); + for(int j = 2; j < w+1; j++) + { + for(int c=0;c(i,j*channel+c) = output.at(i,(j-1)*channel+c) + box_filter.at(i,(j-1)*channel+c); + } + } - Mat indices = Mat::zeros(h,w,CV_32FC1); - Mat final = Mat::zeros(h,w,CV_32FC3); + Mat indices = Mat::zeros(h,w,CV_32FC1); + Mat final = Mat::zeros(h,w,CV_32FC3); - for(int i=0;i(i,j) = i+1; + for(int i=0;i(i,j) = i+1; - Mat a = Mat::zeros(h,w,CV_32FC1); - Mat b = Mat::zeros(h,w,CV_32FC1); + Mat a = Mat::zeros(h,w,CV_32FC1); + Mat b = Mat::zeros(h,w,CV_32FC1); - for(int c=0;c(i,j) = (c+1)*flag.at(i,j); + for(int c=0;c(i,j) = (c+1)*flag.at(i,j); - for(int i=0;i(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (lower_idx.at(i,j) - 1) * h + indices.at(i,j); - b.at(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (upper_idx.at(i,j) - 1) * h + indices.at(i,j); + for(int i=0;i(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (lower_idx.at(i,j) - 1) * h + indices.at(i,j); + b.at(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (upper_idx.at(i,j) - 1) * h + indices.at(i,j); - } + } - int p,q,r,rem; - int p1,q1,r1,rem1; + int p,q,r,rem; + int p1,q1,r1,rem1; - for(int i=0;i(i,j)/(h*(w+1)); - rem = b.at(i,j) - r*h*(w+1); - q = rem/h; - p = rem - q*h; - if(q==0) - { - p=h; - q=w; - r=r-1; - } - if(p==0) - { - p=h; - q=q-1; - } - - - r1 = a.at(i,j)/(h*(w+1)); - rem1 = a.at(i,j) - r1*h*(w+1); - q1 = rem1/h; - p1 = rem1 - q1*h; - if(p1==0) - { - p1=h; - q1=q1-1; - } + r = b.at(i,j)/(h*(w+1)); + rem = b.at(i,j) - r*h*(w+1); + q = rem/h; + p = rem - q*h; + if(q==0) + { + p=h; + q=w; + r=r-1; + } + if(p==0) + { + p=h; + q=q-1; + } - final.at(i,j*channel+2-c) = (box_filter.at(p-1,q*channel+(2-r)) - box_filter.at(p1-1,q1*channel+(2-r1))) - /(upper_idx.at(i,j) - lower_idx.at(i,j)); - } - } - } + r1 = a.at(i,j)/(h*(w+1)); + rem1 = a.at(i,j) - r1*h*(w+1); + q1 = rem1/h; + p1 = rem1 - q1*h; + if(p1==0) + { + p1=h; + q1=q1-1; + } - for(int i=0;i(i,j*channel+c) = final.at(i,j*channel+c); + final.at(i,j*channel+2-c) = (box_filter.at(p-1,q*channel+(2-r)) - box_filter.at(p1-1,q1*channel+(2-r1))) + /(upper_idx.at(i,j) - lower_idx.at(i,j)); + } + } + } + + for(int i=0;i(i,j*channel+c) = final.at(i,j*channel+c); } void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r) { - int h = img.size().height; - int w = img.size().width; - int channel = img.channels(); + int h = img.size().height; + int w = img.size().width; + int channel = img.channels(); - //////////////////////////////////// horizontal and vertical partial derivatives ///////////////////////////////// + //////////////////////////////////// horizontal and vertical partial derivatives ///////////////////////////////// - Mat derivx = Mat::zeros(h,w-1,CV_32FC3); - Mat derivy = Mat::zeros(h-1,w,CV_32FC3); + Mat derivx = Mat::zeros(h,w-1,CV_32FC3); + Mat derivy = Mat::zeros(h-1,w,CV_32FC3); - diffx(img,derivx); - diffy(img,derivy); + diffx(img,derivx); + diffy(img,derivy); - Mat distx = Mat::zeros(h,w,CV_32FC1); - Mat disty = Mat::zeros(h,w,CV_32FC1); + Mat distx = Mat::zeros(h,w,CV_32FC1); + Mat disty = Mat::zeros(h,w,CV_32FC1); - //////////////////////// Compute the l1-norm distance of neighbor pixels //////////////////////////////////////////////// + //////////////////////// Compute the l1-norm distance of neighbor pixels //////////////////////////////////////////////// - for(int i = 0; i < h; i++) - for(int j = 0,k=1; j < w-1; j++,k++) - for(int c = 0; c < channel; c++) - { - distx.at(i,k) = - distx.at(i,k) + abs(derivx.at(i,j*channel+c)); - } + for(int i = 0; i < h; i++) + for(int j = 0,k=1; j < w-1; j++,k++) + for(int c = 0; c < channel; c++) + { + distx.at(i,k) = + distx.at(i,k) + abs(derivx.at(i,j*channel+c)); + } - for(int i = 0,k=1; i < h-1; i++,k++) - for(int j = 0; j < w; j++) - for(int c = 0; c < channel; c++) - { - disty.at(k,j) = - disty.at(k,j) + abs(derivy.at(i,j*channel+c)); - } + for(int i = 0,k=1; i < h-1; i++,k++) + for(int j = 0; j < w; j++) + for(int c = 0; c < channel; c++) + { + disty.at(k,j) = + disty.at(k,j) + abs(derivy.at(i,j*channel+c)); + } - ////////////////////// Compute the derivatives of the horizontal and vertical domain transforms. ///////////////////////////// + ////////////////////// Compute the derivatives of the horizontal and vertical domain transforms. ///////////////////////////// - horiz = Mat(h,w,CV_32FC1); - vert = Mat(h,w,CV_32FC1); + horiz = Mat(h,w,CV_32FC1); + vert = Mat(h,w,CV_32FC1); - Mat final = Mat(h,w,CV_32FC3); + Mat final = Mat(h,w,CV_32FC3); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - { - horiz.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * distx.at(i,j); - vert.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * disty.at(i,j); - } + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + { + horiz.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * distx.at(i,j); + vert.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * disty.at(i,j); + } - O = Mat(h,w,CV_32FC3); + O = Mat(h,w,CV_32FC3); - for(int i =0;i(i,j*channel+c) = img.at(i,j*channel+c); + for(int i =0;i(i,j*channel+c) = img.at(i,j*channel+c); - O_t = Mat(w,h,CV_32FC3); + O_t = Mat(w,h,CV_32FC3); - if(flags == 2) - { + if(flags == 2) + { - ct_H = Mat(h,w,CV_32FC1); - ct_V = Mat(h,w,CV_32FC1); + ct_H = Mat(h,w,CV_32FC1); + ct_V = Mat(h,w,CV_32FC1); - for(int i = 0; i < h; i++) - { - ct_H.at(i,0) = horiz.at(i,0); - for(int j = 1; j < w; j++) - { - ct_H.at(i,j) = horiz.at(i,j) + ct_H.at(i,j-1); - } - } + for(int i = 0; i < h; i++) + { + ct_H.at(i,0) = horiz.at(i,0); + for(int j = 1; j < w; j++) + { + ct_H.at(i,j) = horiz.at(i,j) + ct_H.at(i,j-1); + } + } - for(int j = 0; j < w; j++) - { - ct_V.at(0,j) = vert.at(0,j); - for(int i = 1; i < h; i++) - { - ct_V.at(i,j) = vert.at(i,j) + ct_V.at(i-1,j); - } - } - } + for(int j = 0; j < w; j++) + { + ct_V.at(0,j) = vert.at(0,j); + for(int i = 1; i < h; i++) + { + ct_V.at(i,j) = vert.at(i,j) + ct_V.at(i-1,j); + } + } + } } + void Domain_Filter::filter(const Mat &img, Mat &res, float sigma_s = 60, float sigma_r = 0.4, int flags = 1) { - int no_of_iter = 3; - int h = img.size().height; - int w = img.size().width; - float sigma_h = sigma_s; + int no_of_iter = 3; + int h = img.size().height; + int w = img.size().width; + float sigma_h = sigma_s; - init(img,flags,sigma_s,sigma_r); + init(img,flags,sigma_s,sigma_r); - if(flags == 1) - { + if(flags == 1) + { + Mat vert_t = vert.t(); - Mat vert_t = vert.t(); + for(int i=0;i(k,j) = (shade_factor * (penx.at(k,j) + peny_t.at(k,j))); + + if(i==0) + { + sketch = pen_res.clone(); + + for(int k = 0; k < h; k++) + for(int j = 0; j < w; j++) + { + Y_channel.at(k,j) = color_sketch.at(k,j*channel+0); + U_channel.at(k,j) = color_sketch.at(k,j*channel+1); + V_channel.at(k,j) = color_sketch.at(k,j*channel+2); + } + + + for(int k=0;k(k,j) = pen_res.at(k,j); + + // cvMerge(Y_channel,U_channel,V_channel,0,color_sketch); + for(int k = 0; k < h; k++) + for(int j = 0; j < w; j++) + { + color_sketch.at(k,j*channel+0) = Y_channel.at(k,j); + color_sketch.at(k,j*channel+1) = U_channel.at(k,j); + color_sketch.at(k,j*channel+2) = V_channel.at(k,j); + } + + cvtColor(color_sketch,color_res,COLOR_YCrCb2BGR); + + } + + } - O = O_t.t(); - } - } - - res = O.clone(); } diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp index 92beb02fe8..c67794ed7a 100644 --- a/modules/photo/src/seamless_cloning.cpp +++ b/modules/photo/src/seamless_cloning.cpp @@ -39,7 +39,6 @@ // //M*/ - #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" @@ -55,11 +54,11 @@ using namespace cv; void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags) { - Mat src = _src.getMat(); - Mat dest = _dst.getMat(); - Mat mask = _mask.getMat(); - _blend.create(dest.size(), CV_8UC3); - Mat blend = _blend.getMat(); + Mat src = _src.getMat(); + Mat dest = _dst.getMat(); + Mat mask = _mask.getMat(); + _blend.create(dest.size(), CV_8UC3); + Mat blend = _blend.getMat(); int minx = INT_MAX, miny = INT_MAX, maxx = INT_MIN, maxy = INT_MIN; int h = mask.size().height; @@ -134,14 +133,14 @@ void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float r, float g, float b) { - Mat src = _src.getMat(); - Mat mask = _mask.getMat(); - _dst.create(src.size(), src.type()); - Mat blend = _dst.getMat(); - - float red = r; - float green = g; - float blue = b; + Mat src = _src.getMat(); + Mat mask = _mask.getMat(); + _dst.create(src.size(), src.type()); + Mat blend = _dst.getMat(); + + float red = r; + float green = g; + float blue = b; Mat gray = Mat::zeros(mask.size(),CV_8UC1); @@ -149,7 +148,7 @@ void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float cvtColor(mask, gray, COLOR_BGR2GRAY ); else gray = mask; - + Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); int channel = 3; @@ -174,12 +173,12 @@ void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float a, float b) { - Mat src = _src.getMat(); - Mat mask = _mask.getMat(); - _dst.create(src.size(), src.type()); - Mat blend = _dst.getMat(); - float alpha = a; - float beta = b; + Mat src = _src.getMat(); + Mat mask = _mask.getMat(); + _dst.create(src.size(), src.type()); + Mat blend = _dst.getMat(); + float alpha = a; + float beta = b; Mat gray = Mat::zeros(mask.size(),CV_8UC1); @@ -203,19 +202,20 @@ void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, } } - + Cloning obj; obj.illum_change(src,cs_mask,gray,blend,alpha,beta); } -void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst) +void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst, + double low_threshold, double high_threshold, int kernel_size) { - Mat src = _src.getMat(); - Mat mask = _mask.getMat(); - _dst.create(src.size(), src.type()); - Mat blend = _dst.getMat(); + Mat src = _src.getMat(); + Mat mask = _mask.getMat(); + _dst.create(src.size(), src.type()); + Mat blend = _dst.getMat(); Mat gray = Mat::zeros(mask.size(),CV_8UC1); @@ -239,8 +239,8 @@ void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst) } } - + Cloning obj; - obj.texture_flatten(src,cs_mask,gray,blend); + obj.texture_flatten(src,cs_mask,gray,low_threshold,high_threshold,kernel_size,blend); } diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index a59cb5d16b..f039d2974d 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -39,7 +39,6 @@ // //M*/ - #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" @@ -74,9 +73,9 @@ class Cloning void transpose(double *mat, double *mat_t,int h,int w); void poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result); void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num); - void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red, float green, float blue); + void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red_mul, float green_mul, float blue_mul); void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta); - void texture_flatten(Mat &I, Mat &mask, Mat &wmask, Mat &final); + void texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, double high_threhold, int kernel_size, Mat &final); }; void Cloning::getGradientx( const Mat &img, Mat &gx) @@ -94,6 +93,7 @@ void Cloning::getGradientx( const Mat &img, Mat &gx) (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); } } + void Cloning::getGradienty( const Mat &img, Mat &gy) { int w = img.size().width; @@ -110,6 +110,7 @@ void Cloning::getGradienty( const Mat &img, Mat &gy) } } + void Cloning::lapx( const Mat &img, Mat &gxx) { int w = img.size().width; @@ -125,6 +126,7 @@ void Cloning::lapx( const Mat &img, Mat &gxx) (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); } } + void Cloning::lapy( const Mat &img, Mat &gyy) { int w = img.size().width; @@ -242,6 +244,7 @@ void Cloning::transpose(double *mat, double *mat_t,int h,int w) tmp.release(); } + void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) { @@ -275,7 +278,6 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) + (int)bound.at(i-1,j) + (int)bound.at(i+1,j); } - Mat diff = Mat(h,w,CV_32FC1); for(int i =0;i(i,j*channel+0) = blue; - factor.at(i,j*channel+1) = green; - factor.at(i,j*channel+2) = red; + factor.at(i,j*channel+0) = blue_mul; + factor.at(i,j*channel+1) = green_mul; + factor.at(i,j*channel+2) = red_mul; } - - for(int i=0;i < h; i++) for(int j=0; j < w; j++) for(int c=0;cget_data_path()) + "cloning/Feature_Exchange/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Monochrome_Transfer/"; string original_path1 = folder + "source1.png"; string original_path2 = folder + "destination1.png"; string original_path3 = folder + "mask.png"; @@ -174,7 +174,7 @@ TEST(Photo_SeamlessClone_textureFlattening, regression) ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2; Mat result; - textureFlattening(source, mask, result); + textureFlattening(source, mask, result, 30, 45, 3); imwrite(folder + "cloned.png", result); diff --git a/modules/photo/test/test_npr.cpp b/modules/photo/test/test_npr.cpp new file mode 100644 index 0000000000..0a4b2c56ef --- /dev/null +++ b/modules/photo/test/test_npr.cpp @@ -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) 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" +#include "opencv2/photo.hpp" +#include + +using namespace cv; +using namespace std; + + +TEST(Photo_NPR_EdgePreserveSmoothing_RecursiveFilter, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Smoothing/"; + string original_path = folder + "test1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; + + Mat result; + edgePreservingFilter(source,result,1); + + imwrite(folder + "smoothened_RF.png", result); + +} + +TEST(Photo_NPR_EdgePreserveSmoothing_NormConvFilter, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Smoothing/"; + string original_path = folder + "test1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; + + Mat result; + edgePreservingFilter(source,result,2); + + imwrite(folder + "smoothened_NCF.png", result); + +} + +TEST(Photo_NPR_DetailEnhance, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Detail_Enhance/"; + string original_path = folder + "test1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; + + Mat result; + detailEnhance(source,result); + + imwrite(folder + "detail_enhanced.png", result); + +} + +TEST(Photo_NPR_PencilSketch, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Pencil_Sketch/"; + string original_path = folder + "test1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; + + Mat result,result1; + pencilSketch(source,result,result1,10,.1,.03); + + imwrite(folder + "pencil_sketch.png", result); + imwrite(folder + "color_pencil_sketch.png", result1); + +} + +TEST(Photo_NPR_Stylization, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Stylization/"; + string original_path = folder + "test1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; + + Mat result; + stylization(source,result); + + imwrite(folder + "stylized.png", result); + +} + +TEST(Photo_NPR_EdgeEnhance, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Edge_Enhance/"; + string original_path = folder + "test1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; + + Mat result; + edgeEnhance(source,result); + + imwrite(folder + "edge_enhanced.png", result); + +} diff --git a/samples/cpp/cloning.cpp b/samples/cpp/cloning.cpp index 9a41ce229b..84458fd4fe 100644 --- a/samples/cpp/cloning.cpp +++ b/samples/cpp/cloning.cpp @@ -56,18 +56,19 @@ char src[50]; char dest[50]; int var = 0; -int flag = 0; -int flag1 = 0; +int flag = 0, flag1 = 0, flag4 = 0; -int minx,miny,maxx,maxy,lenx,leny; -int minxd,minyd,maxxd,maxyd,lenxd,lenyd; +int minx, miny, maxx, maxy, lenx, leny; +int minxd, minyd, maxxd, maxyd, lenxd, lenyd; -int channel,num; +int channel, num, kernel_size; float alpha,beta; float red, green, blue; +double low_t, high_t; + void source(int event, int x, int y, int, void*) { @@ -159,7 +160,7 @@ void source(int event, int x, int y, int, void*) } else if(num == 6) { - textureFlattening(img0,res1,blend); + textureFlattening(img0,res1,blend,low_t,high_t,kernel_size); imshow("Texture Flattened", blend); waitKey(0); } @@ -176,11 +177,12 @@ void source(int event, int x, int y, int, void*) flag1 = 0; minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; imshow("Source", img0); + if(num == 1 || num == 2 || num == 3) + imshow("Destination",img2); drag = 0; } } - void destination(int event, int x, int y, int, void*) { @@ -190,6 +192,7 @@ void destination(int event, int x, int y, int, void*) im1 = img2.clone(); if (event == EVENT_LBUTTONDOWN) { + flag4 = 1; if(flag1 == 1) { point = Point(x, y); @@ -386,14 +389,12 @@ int main(int argc, char **argv) res1 = Mat::zeros(img0.size(),CV_8UC1); final = Mat::zeros(img0.size(),CV_8UC3); - //////////// source image /////////////////// namedWindow("Source", 1); setMouseCallback("Source", source, NULL); imshow("Source", img0); - } else if(num == 5) { @@ -416,12 +417,20 @@ int main(int argc, char **argv) setMouseCallback("Source", source, NULL); imshow("Source", img0); - } else if(num == 6) { checkfile(s); + cout << "low_threshold: "; + cin >> low_t; + + cout << "high_threshold: "; + cin >> high_t; + + cout << "kernel_size: "; + cin >> kernel_size; + img0 = imread(src); res1 = Mat::zeros(img0.size(),CV_8UC1); @@ -434,13 +443,16 @@ int main(int argc, char **argv) imshow("Source", img0); } + int flag3 = 0; + while(true) { char key = waitKey(0); - if(key == 'd') + if(key == 'd' && flag3 == 0) { flag1 = 1; + flag3 = 1; img1 = img0.clone(); for(int i = var; i < numpts ; i++) pts[i] = point; @@ -490,13 +502,15 @@ int main(int argc, char **argv) } var = 0; flag1 = 0; + flag3 = 0; + flag4 = 0; minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; imshow("Source", img0); if(num == 1 || num == 2 || num == 3) imshow("Destination",img2); drag = 0; } - else if ((num == 1 || num == 2 || num == 3) && key == 'c' && flag1 == 1) + else if ((num == 1 || num == 2 || num == 3) && key == 'c' && flag1 == 1 && flag4 == 1) { seamlessClone(img0,img2,res1,point,blend,num); imshow("Cloned Image", blend); @@ -516,14 +530,12 @@ int main(int argc, char **argv) } else if (num == 6 && key == 'c' && flag1 == 1) { - textureFlattening(img0,res1,blend); + textureFlattening(img0,res1,blend,low_t,high_t,kernel_size); imshow("Texture Flattened", blend); imwrite("cloned.png",blend); } else if(key == 'q') exit(0); - } - waitKey(0); } diff --git a/samples/cpp/cloning_example.cpp b/samples/cpp/cloning_example.cpp new file mode 100644 index 0000000000..6c31d2f44e --- /dev/null +++ b/samples/cpp/cloning_example.cpp @@ -0,0 +1,243 @@ +/* +* cloning.cpp +* +* Author: +* Siddharth Kherada +* +* This tutorial demonstrates how to use OpenCV seamless cloning +* module without GUI. +* +* 1- Normal Cloning +* 2- Mixed Cloning +* 3- Monochrome Transfer +* 4- Color Change +* 5- Illumination change +* 6- Texture Flattening + +* The program takes as input a source and a destination image (for 1-3 methods) +* and ouputs the cloned image. +*/ + +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include + +using namespace std; +using namespace cv; + +int main(int argc, char **argv) +{ + cout << endl; + cout << "Cloning Module" << endl; + cout << "---------------" << endl; + cout << "Options: " << endl; + cout << endl; + cout << "1) Normal Cloning " << endl; + cout << "2) Mixed Cloning " << endl; + cout << "3) Monochrome Transfer " << endl; + cout << "4) Local Color Change " << endl; + cout << "5) Local Illumination Change " << endl; + cout << "6) Texture Flattening " << endl; + cout << endl; + cout << "Press number 1-6 to choose from above techniques: "; + int num; + cin >> num; + cout << endl; + + if(num == 1) + { + string folder = "cloning/Normal_Cloning/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(destination.empty()) + { + cout << "Could not load destination image " << original_path2 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path3 << endl; + exit(0); + } + + Mat result; + Point p; + p.x = 400; + p.y = 100; + + seamlessClone(source, destination, mask, p, result, 1); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 2) + { + string folder = "cloning/Mixed_Cloning/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(destination.empty()) + { + cout << "Could not load destination image " << original_path2 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path3 << endl; + exit(0); + } + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + + seamlessClone(source, destination, mask, p, result, 2); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 3) + { + string folder = "cloning/Monochrome_Transfer/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(destination.empty()) + { + cout << "Could not load destination image " << original_path2 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path3 << endl; + exit(0); + } + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + + seamlessClone(source, destination, mask, p, result, 3); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 4) + { + string folder = "cloning/Color_Change/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path2 << endl; + exit(0); + } + + Mat result; + + colorChange(source, mask, result, 1.5, .5, .5); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 5) + { + string folder = "cloning/Illumination_Change/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path2 << endl; + exit(0); + } + + Mat result; + + illuminationChange(source, mask, result, .2, .4); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 6) + { + string folder = "cloning/Texture_Flattening/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path2 << endl; + exit(0); + } + + Mat result; + + textureFlattening(source, mask, result, 30, 45, 3); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + waitKey(0); +} diff --git a/samples/cpp/npr_demo.cpp b/samples/cpp/npr_demo.cpp new file mode 100644 index 0000000000..871fd32405 --- /dev/null +++ b/samples/cpp/npr_demo.cpp @@ -0,0 +1,107 @@ +/* +* npr_demo.cpp +* +* Author: +* Siddharth Kherada +* +* This tutorial demonstrates how to use OpenCV Non-Photorealistic Rendering Module. +* 1) Edge Preserve Smoothing +* -> Using Normalized convolution Filter +* -> Using Recursive Filter +* 2) Detail Enhancement +* 3) Pencil sketch/Color Pencil Drawing +* 4) Stylization +* 5) Edge Enhancement +* +*/ + +#include +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include + +using namespace std; +using namespace cv; + +int main(int argc, char* argv[]) +{ + int num,type; + + int flag = 0; + + Mat I = imread(argv[1]); + + + if(argc < 2) + { + cout << "usage: " << argv[0] << " " << endl; + exit(0); + } + + if(!I.data) + { + cout << "Image not found" << endl; + exit(0); + } + + cout << endl; + cout << " Edge Preserve Filter" << endl; + cout << "----------------------" << endl; + + cout << "Options: " << endl; + cout << endl; + + cout << "1) Edge Preserve Smoothing" << endl; + cout << " -> Using Normalized convolution Filter" << endl; + cout << " -> Using Recursive Filter" << endl; + cout << "2) Detail Enhancement" << endl; + cout << "3) Pencil sketch/Color Pencil Drawing" << endl; + cout << "4) Stylization" << endl; + cout << "5) Edge Enhancement" << endl; + cout << endl; + + cout << "Press number 1-5 to choose from above techniques: "; + + cin >> num; + + Mat img; + + if(num == 1) + { + cout << endl; + cout << "Press 1 for Normalized Convolution Filter and 2 for Recursive Filter: "; + + cin >> type; + + edgePreservingFilter(I,img,type); + imshow("Edge Preserve Smoothing",img); + + } + else if(num == 2) + { + detailEnhance(I,img); + imshow("Detail Enhanced",img); + } + else if(num == 3) + { + Mat img1; + pencilSketch(I,img1, img, 10 ,.1,.03); + imshow("Pencil Sketch",img1); + imshow("Color Pencil Sketch",img); + } + else if(num == 4) + { + stylization(I,img); + imshow("Stylization",img); + } + else if(num == 5) + { + edgeEnhance(I,img); + imshow("Edge Enhance",img); + } + + waitKey(0); +} From 50c19423f9c4af5d3c81f75f4a3dd0a4b4abc3f3 Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 13 Sep 2013 18:25:23 +0530 Subject: [PATCH 25/97] cloning demo added --- samples/cpp/cloning_demo.cpp | 243 +++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 samples/cpp/cloning_demo.cpp diff --git a/samples/cpp/cloning_demo.cpp b/samples/cpp/cloning_demo.cpp new file mode 100644 index 0000000000..7952174648 --- /dev/null +++ b/samples/cpp/cloning_demo.cpp @@ -0,0 +1,243 @@ +/* +* cloning_demo.cpp +* +* Author: +* Siddharth Kherada +* +* This tutorial demonstrates how to use OpenCV seamless cloning +* module without GUI. +* +* 1- Normal Cloning +* 2- Mixed Cloning +* 3- Monochrome Transfer +* 4- Color Change +* 5- Illumination change +* 6- Texture Flattening + +* The program takes as input a source and a destination image (for 1-3 methods) +* and ouputs the cloned image. +*/ + +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include + +using namespace std; +using namespace cv; + +int main(int argc, char **argv) +{ + cout << endl; + cout << "Cloning Module" << endl; + cout << "---------------" << endl; + cout << "Options: " << endl; + cout << endl; + cout << "1) Normal Cloning " << endl; + cout << "2) Mixed Cloning " << endl; + cout << "3) Monochrome Transfer " << endl; + cout << "4) Local Color Change " << endl; + cout << "5) Local Illumination Change " << endl; + cout << "6) Texture Flattening " << endl; + cout << endl; + cout << "Press number 1-6 to choose from above techniques: "; + int num; + cin >> num; + cout << endl; + + if(num == 1) + { + string folder = "cloning/Normal_Cloning/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(destination.empty()) + { + cout << "Could not load destination image " << original_path2 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path3 << endl; + exit(0); + } + + Mat result; + Point p; + p.x = 400; + p.y = 100; + + seamlessClone(source, destination, mask, p, result, 1); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 2) + { + string folder = "cloning/Mixed_Cloning/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(destination.empty()) + { + cout << "Could not load destination image " << original_path2 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path3 << endl; + exit(0); + } + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + + seamlessClone(source, destination, mask, p, result, 2); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 3) + { + string folder = "cloning/Monochrome_Transfer/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(destination.empty()) + { + cout << "Could not load destination image " << original_path2 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path3 << endl; + exit(0); + } + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + + seamlessClone(source, destination, mask, p, result, 3); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 4) + { + string folder = "cloning/Color_Change/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path2 << endl; + exit(0); + } + + Mat result; + + colorChange(source, mask, result, 1.5, .5, .5); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 5) + { + string folder = "cloning/Illumination_Change/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path2 << endl; + exit(0); + } + + Mat result; + + illuminationChange(source, mask, result, .2, .4); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 6) + { + string folder = "cloning/Texture_Flattening/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path2 << endl; + exit(0); + } + + Mat result; + + textureFlattening(source, mask, result, 30, 45, 3); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + waitKey(0); +} From 7ab43585aa127225810bb497c639f529ed1d3cad Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 13 Sep 2013 18:27:02 +0530 Subject: [PATCH 26/97] remove cloning_example.cpp --- samples/cpp/cloning_example.cpp | 243 -------------------------------- 1 file changed, 243 deletions(-) delete mode 100644 samples/cpp/cloning_example.cpp diff --git a/samples/cpp/cloning_example.cpp b/samples/cpp/cloning_example.cpp deleted file mode 100644 index 6c31d2f44e..0000000000 --- a/samples/cpp/cloning_example.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* -* cloning.cpp -* -* Author: -* Siddharth Kherada -* -* This tutorial demonstrates how to use OpenCV seamless cloning -* module without GUI. -* -* 1- Normal Cloning -* 2- Mixed Cloning -* 3- Monochrome Transfer -* 4- Color Change -* 5- Illumination change -* 6- Texture Flattening - -* The program takes as input a source and a destination image (for 1-3 methods) -* and ouputs the cloned image. -*/ - -#include "opencv2/photo.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" -#include "opencv2/core.hpp" -#include -#include - -using namespace std; -using namespace cv; - -int main(int argc, char **argv) -{ - cout << endl; - cout << "Cloning Module" << endl; - cout << "---------------" << endl; - cout << "Options: " << endl; - cout << endl; - cout << "1) Normal Cloning " << endl; - cout << "2) Mixed Cloning " << endl; - cout << "3) Monochrome Transfer " << endl; - cout << "4) Local Color Change " << endl; - cout << "5) Local Illumination Change " << endl; - cout << "6) Texture Flattening " << endl; - cout << endl; - cout << "Press number 1-6 to choose from above techniques: "; - int num; - cin >> num; - cout << endl; - - if(num == 1) - { - string folder = "cloning/Normal_Cloning/"; - string original_path1 = folder + "source1.png"; - string original_path2 = folder + "destination1.png"; - string original_path3 = folder + "mask.png"; - - Mat source = imread(original_path1, IMREAD_COLOR); - Mat destination = imread(original_path2, IMREAD_COLOR); - Mat mask = imread(original_path3, IMREAD_COLOR); - - if(source.empty()) - { - cout << "Could not load source image " << original_path1 << endl; - exit(0); - } - if(destination.empty()) - { - cout << "Could not load destination image " << original_path2 << endl; - exit(0); - } - if(mask.empty()) - { - cout << "Could not load mask image " << original_path3 << endl; - exit(0); - } - - Mat result; - Point p; - p.x = 400; - p.y = 100; - - seamlessClone(source, destination, mask, p, result, 1); - - imshow("Output",result); - imwrite(folder + "cloned.png", result); - } - else if(num == 2) - { - string folder = "cloning/Mixed_Cloning/"; - string original_path1 = folder + "source1.png"; - string original_path2 = folder + "destination1.png"; - string original_path3 = folder + "mask.png"; - - Mat source = imread(original_path1, IMREAD_COLOR); - Mat destination = imread(original_path2, IMREAD_COLOR); - Mat mask = imread(original_path3, IMREAD_COLOR); - - if(source.empty()) - { - cout << "Could not load source image " << original_path1 << endl; - exit(0); - } - if(destination.empty()) - { - cout << "Could not load destination image " << original_path2 << endl; - exit(0); - } - if(mask.empty()) - { - cout << "Could not load mask image " << original_path3 << endl; - exit(0); - } - - Mat result; - Point p; - p.x = destination.size().width/2; - p.y = destination.size().height/2; - - seamlessClone(source, destination, mask, p, result, 2); - - imshow("Output",result); - imwrite(folder + "cloned.png", result); - } - else if(num == 3) - { - string folder = "cloning/Monochrome_Transfer/"; - string original_path1 = folder + "source1.png"; - string original_path2 = folder + "destination1.png"; - string original_path3 = folder + "mask.png"; - - Mat source = imread(original_path1, IMREAD_COLOR); - Mat destination = imread(original_path2, IMREAD_COLOR); - Mat mask = imread(original_path3, IMREAD_COLOR); - - if(source.empty()) - { - cout << "Could not load source image " << original_path1 << endl; - exit(0); - } - if(destination.empty()) - { - cout << "Could not load destination image " << original_path2 << endl; - exit(0); - } - if(mask.empty()) - { - cout << "Could not load mask image " << original_path3 << endl; - exit(0); - } - - Mat result; - Point p; - p.x = destination.size().width/2; - p.y = destination.size().height/2; - - seamlessClone(source, destination, mask, p, result, 3); - - imshow("Output",result); - imwrite(folder + "cloned.png", result); - } - else if(num == 4) - { - string folder = "cloning/Color_Change/"; - string original_path1 = folder + "source1.png"; - string original_path2 = folder + "mask.png"; - - Mat source = imread(original_path1, IMREAD_COLOR); - Mat mask = imread(original_path2, IMREAD_COLOR); - - if(source.empty()) - { - cout << "Could not load source image " << original_path1 << endl; - exit(0); - } - if(mask.empty()) - { - cout << "Could not load mask image " << original_path2 << endl; - exit(0); - } - - Mat result; - - colorChange(source, mask, result, 1.5, .5, .5); - - imshow("Output",result); - imwrite(folder + "cloned.png", result); - } - else if(num == 5) - { - string folder = "cloning/Illumination_Change/"; - string original_path1 = folder + "source1.png"; - string original_path2 = folder + "mask.png"; - - Mat source = imread(original_path1, IMREAD_COLOR); - Mat mask = imread(original_path2, IMREAD_COLOR); - - if(source.empty()) - { - cout << "Could not load source image " << original_path1 << endl; - exit(0); - } - if(mask.empty()) - { - cout << "Could not load mask image " << original_path2 << endl; - exit(0); - } - - Mat result; - - illuminationChange(source, mask, result, .2, .4); - - imshow("Output",result); - imwrite(folder + "cloned.png", result); - } - else if(num == 6) - { - string folder = "cloning/Texture_Flattening/"; - string original_path1 = folder + "source1.png"; - string original_path2 = folder + "mask.png"; - - Mat source = imread(original_path1, IMREAD_COLOR); - Mat mask = imread(original_path2, IMREAD_COLOR); - - if(source.empty()) - { - cout << "Could not load source image " << original_path1 << endl; - exit(0); - } - if(mask.empty()) - { - cout << "Could not load mask image " << original_path2 << endl; - exit(0); - } - - Mat result; - - textureFlattening(source, mask, result, 30, 45, 3); - - imshow("Output",result); - imwrite(folder + "cloned.png", result); - } - waitKey(0); -} From f8b00e52698d2caefbb6c8dc9417c720d9b1e794 Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 13 Sep 2013 18:28:03 +0530 Subject: [PATCH 27/97] renamed --- samples/cpp/{cloning.cpp => cloning_gui.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename samples/cpp/{cloning.cpp => cloning_gui.cpp} (100%) diff --git a/samples/cpp/cloning.cpp b/samples/cpp/cloning_gui.cpp similarity index 100% rename from samples/cpp/cloning.cpp rename to samples/cpp/cloning_gui.cpp From 01e1ccfa88d4df8667270a5f400ecf655aa08bec Mon Sep 17 00:00:00 2001 From: siddharth Date: Sat, 14 Sep 2013 16:47:44 +0530 Subject: [PATCH 28/97] cloning_demo error removed --- samples/cpp/cloning_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/cpp/cloning_demo.cpp b/samples/cpp/cloning_demo.cpp index 7952174648..1992b65e98 100644 --- a/samples/cpp/cloning_demo.cpp +++ b/samples/cpp/cloning_demo.cpp @@ -28,7 +28,7 @@ using namespace std; using namespace cv; -int main(int argc, char **argv) +int main() { cout << endl; cout << "Cloning Module" << endl; From 75b76554bf9478b27e88a8ec5ef1ff239ff0bfba Mon Sep 17 00:00:00 2001 From: siddharth Date: Sat, 14 Sep 2013 17:06:26 +0530 Subject: [PATCH 29/97] errors in samples/cpp removed --- samples/cpp/cloning_gui.cpp | 6 +++++- samples/cpp/create_mask.cpp | 9 +++++++++ samples/cpp/npr_demo.cpp | 11 ++++------- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/samples/cpp/cloning_gui.cpp b/samples/cpp/cloning_gui.cpp index 84458fd4fe..1d742fdd51 100644 --- a/samples/cpp/cloning_gui.cpp +++ b/samples/cpp/cloning_gui.cpp @@ -69,6 +69,10 @@ float red, green, blue; double low_t, high_t; +void source(int, int, int, int, void*); +void destination(int, int, int, int, void*); +void checkfile(char*); + void source(int event, int x, int y, int, void*) { @@ -304,7 +308,7 @@ void checkfile(char *file) } } -int main(int argc, char **argv) +int main() { cout << endl; cout << "Cloning Module" << endl; diff --git a/samples/cpp/create_mask.cpp b/samples/cpp/create_mask.cpp index 03055e99e0..59905f1403 100644 --- a/samples/cpp/create_mask.cpp +++ b/samples/cpp/create_mask.cpp @@ -36,6 +36,8 @@ int minx,miny,maxx,maxy,lenx,leny; int channel; +void mouseHandler(int, int, int, int, void*); + void mouseHandler(int event, int x, int y, int, void*) { @@ -123,6 +125,13 @@ void mouseHandler(int event, int x, int y, int, void*) int main(int argc, char **argv) { + + if(argc != 2) + { + cout << "usage: " << argv[0] << " " << endl; + exit(1); + } + Mat src = imread(argv[1]); minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; diff --git a/samples/cpp/npr_demo.cpp b/samples/cpp/npr_demo.cpp index 871fd32405..e5e2528f13 100644 --- a/samples/cpp/npr_demo.cpp +++ b/samples/cpp/npr_demo.cpp @@ -28,19 +28,16 @@ using namespace cv; int main(int argc, char* argv[]) { - int num,type; - - int flag = 0; - - Mat I = imread(argv[1]); - - if(argc < 2) { cout << "usage: " << argv[0] << " " << endl; exit(0); } + int num,type; + + Mat I = imread(argv[1]); + if(!I.data) { cout << "Image not found" << endl; From 05c7c9325adcbfdd834891a79ec0d4e0a980273d Mon Sep 17 00:00:00 2001 From: siddharth Date: Sat, 14 Sep 2013 18:59:55 +0530 Subject: [PATCH 30/97] cloning_gui.cpp updated --- samples/cpp/cloning_gui.cpp | 89 +++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/samples/cpp/cloning_gui.cpp b/samples/cpp/cloning_gui.cpp index 1d742fdd51..4ba6b61dad 100644 --- a/samples/cpp/cloning_gui.cpp +++ b/samples/cpp/cloning_gui.cpp @@ -190,7 +190,6 @@ void source(int event, int x, int y, int, void*) void destination(int event, int x, int y, int, void*) { - Mat im1; minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; im1 = img2.clone(); @@ -250,7 +249,6 @@ void destination(int event, int x, int y, int, void*) } } - const Point* pts6[1] = {&pts2[0]}; fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0); @@ -274,40 +272,6 @@ void destination(int event, int x, int y, int, void*) im1.release(); } -void checkfile(char *file) -{ - while(1) - { - printf("Enter %s Image: ",file); - if(!strcmp(file,"Source")) - { - cin >> src; - if(access( src, F_OK ) != -1 ) - { - break; - } - else - { - printf("Image doesn't exist\n"); - } - } - else if(!strcmp(file,"Destination")) - { - cin >> dest; - - if(access( dest, F_OK ) != -1 ) - { - break; - } - else - { - printf("Image doesn't exist\n"); - } - - } - } -} - int main() { cout << endl; @@ -348,13 +312,28 @@ int main() if(num == 1 || num == 2 || num == 3) { - checkfile(s); - checkfile(d); + string src,dest; + cout << "Enter Source Image: "; + cin >> src; + + cout << "Enter Destination Image: "; + cin >> dest; img0 = imread(src); - + img2 = imread(dest); + if(!img0.data) + { + cout << "Source Image does not exist" << endl; + exit(0); + } + if(!img2.data) + { + cout << "Destination Image does not exist" << endl; + exit(0); + } + channel = img0.channels(); res = Mat::zeros(img2.size(),CV_8UC1); @@ -376,8 +355,10 @@ int main() } else if(num == 4) { - checkfile(s); - + string src; + cout << "Enter Source Image: "; + cin >> src; + cout << "Enter RGB values: " << endl; cout << "Red: "; cin >> red; @@ -390,6 +371,12 @@ int main() img0 = imread(src); + if(!img0.data) + { + cout << "Source Image does not exist" << endl; + exit(0); + } + res1 = Mat::zeros(img0.size(),CV_8UC1); final = Mat::zeros(img0.size(),CV_8UC3); @@ -402,7 +389,9 @@ int main() } else if(num == 5) { - checkfile(s); + string src; + cout << "Enter Source Image: "; + cin >> src; cout << "alpha: "; cin >> alpha; @@ -412,6 +401,12 @@ int main() img0 = imread(src); + if(!img0.data) + { + cout << "Source Image does not exist" << endl; + exit(0); + } + res1 = Mat::zeros(img0.size(),CV_8UC1); final = Mat::zeros(img0.size(),CV_8UC3); @@ -424,7 +419,9 @@ int main() } else if(num == 6) { - checkfile(s); + string src; + cout << "Enter Source Image: "; + cin >> src; cout << "low_threshold: "; cin >> low_t; @@ -437,6 +434,12 @@ int main() img0 = imread(src); + if(!img0.data) + { + cout << "Source Image does not exist" << endl; + exit(0); + } + res1 = Mat::zeros(img0.size(),CV_8UC1); final = Mat::zeros(img0.size(),CV_8UC3); From f85a615f3fbe2f8a20c5150eead1868837aa8dda Mon Sep 17 00:00:00 2001 From: siddharth Date: Sat, 14 Sep 2013 19:12:25 +0530 Subject: [PATCH 31/97] whitespaces removed and other minor changes to fix build error Update 1 update 2 Update 3 Update 4 Update 5 update 6 Update 7 Update 8 Update 9 Update 10 Update 11 Update 12 Update 13 Update 14 Update 15 Update 16 Update 17 Update 18 Update 19 Update 20 Update 21 Update 22 Removed Headers Update 23 Update 24 Update 25 Update 26 Update 27 Update 28 --- modules/photo/doc/cloning.rst | 30 +-- modules/photo/doc/decolor.rst | 1 - modules/photo/doc/npr.rst | 35 ++- modules/photo/doc/photo.rst | 5 +- modules/photo/include/opencv2/photo.hpp | 106 ++++----- modules/photo/src/contrast_preserve.cpp | 20 +- modules/photo/src/contrast_preserve.hpp | 19 +- modules/photo/src/npr.cpp | 283 ++++++++++++------------ modules/photo/src/npr.hpp | 50 ++--- modules/photo/src/seamless_cloning.cpp | 4 - modules/photo/src/seamless_cloning.hpp | 54 ++--- modules/photo/test/test_cloning.cpp | 3 +- modules/photo/test/test_decolor.cpp | 1 - modules/photo/test/test_npr.cpp | 12 +- samples/cpp/cloning_demo.cpp | 34 +-- samples/cpp/cloning_gui.cpp | 172 +++++++------- samples/cpp/create_mask.cpp | 159 +++++++------ 17 files changed, 479 insertions(+), 509 deletions(-) diff --git a/modules/photo/doc/cloning.rst b/modules/photo/doc/cloning.rst index 11e9bce135..3a115e8390 100644 --- a/modules/photo/doc/cloning.rst +++ b/modules/photo/doc/cloning.rst @@ -9,16 +9,16 @@ Image editing tasks concern either global changes (color/intensity corrections, Here we are interested in achieving local changes, ones that are restricted to a region manually selected (ROI), in a seamless and effortless manner. The extent of the changes ranges from slight distortions to complete replacement by novel content. -.. ocv:function:: void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, OutputArray result, int flags) +.. ocv:function:: void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, OutputArray blend, int flags) :param src: Input 8-bit 3-channel image. :param dst: Input 8-bit 3-channel image. - + :param mask: Input 8-bit 1 or 3-channel image. - - :param Point: Point in dst image where object is placed. - + + :param p: Point in dst image where object is placed. + :param result: Output image with the same size and type as ``dst``. :param flags: Cloning method that could be one of the following: @@ -29,7 +29,7 @@ The extent of the changes ranges from slight distortions to complete replacement masking might be time consuming and often leaves an undesirable halo. Seamless cloning, even averaged with the original image, is not effective. Mixed seamless cloning based on a loose selection proves effective. - + * **FEATURE_EXCHANGE** Feature exchange allows the user to replace easily certain features of one object by alternative features. @@ -44,17 +44,17 @@ Given an original color image, two differently colored versions of this image ca :param src: Input 8-bit 3-channel image. :param mask: Input 8-bit 1 or 3-channel image. - + :param dst: Output image with the same size and type as ``src`` . :param red_mul: R-channel multiply factor. - + :param green_mul: G-channel multiply factor. - + :param blue_mul: B-channel multiply factor. Multiplication factor is between .5 to 2.5. - + illuminationChange ------------------ @@ -66,11 +66,11 @@ solver, modifies locally the apparent illumination of an image. :param src: Input 8-bit 3-channel image. :param mask: Input 8-bit 1 or 3-channel image. - + :param dst: Output image with the same size and type as ``src``. :param alpha: Value ranges between 0-2. - + :param beta: Value ranges between 0-2. This is useful to highlight under-exposed foreground objects or to reduce specular reflections. @@ -85,13 +85,13 @@ region, giving its contents a flat aspect. Here Canny Edge Detector is used. :param src: Input 8-bit 3-channel image. :param mask: Input 8-bit 1 or 3-channel image. - + :param dst: Output image with the same size and type as ``src``. :param low_threshold: Range from 0 to 100. - + :param high_threshold: Value > 100. - + :param kernel_size: The size of the Sobel kernel to be used. **NOTE:** diff --git a/modules/photo/doc/decolor.rst b/modules/photo/doc/decolor.rst index 061b2b18c6..cf7b9b9c4c 100644 --- a/modules/photo/doc/decolor.rst +++ b/modules/photo/doc/decolor.rst @@ -17,4 +17,3 @@ Transforms a color image to a grayscale image. It is a basic tool in digital pri :param color_boost: Output 8-bit 3-channel image. This function is to be applied on color images. - diff --git a/modules/photo/doc/npr.rst b/modules/photo/doc/npr.rst index db56c6955c..e547689876 100644 --- a/modules/photo/doc/npr.rst +++ b/modules/photo/doc/npr.rst @@ -8,20 +8,20 @@ edgePreservingFilter Filtering is the fundamental operation in image and video processing. Edge-preserving smoothing filters are used in many different applications. -.. ocv:function:: void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4); +.. ocv:function:: void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4) :param src: Input 8-bit 3-channel image. :param dst: Output 8-bit 3-channel image. - + :param flags: Edge preserving filters: - * **RECURS_FILTER** + * **RECURS_FILTER** - * **NORMCONV_FILTER** + * **NORMCONV_FILTER** :param sigma_s: Range between 0 to 200. - + :param sigma_r: Range between 0 to 1. @@ -29,33 +29,33 @@ detailEnhance ------------- This filter enhances the details of a particular image. -.. ocv:function:: void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, float sigma_r = 0.15); +.. ocv:function:: void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, float sigma_r = 0.15) :param src: Input 8-bit 3-channel image. :param dst: Output image with the same size and type as ``src``. - :param sigma_s: Range between 0 to 200. - + :param sigma_s: Range between 0 to 200. + :param sigma_r: Range between 0 to 1. - + pencilSketch ------------ Pencil-like non-photorealistic line drawing -.. ocv:function:: void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); +.. ocv:function:: void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02) :param src: Input 8-bit 3-channel image. :param dst1: Output 8-bit 1-channel image. - + :param dst2: Output image with the same size and type as ``src``. :param sigma_s: Range between 0 to 200. - + :param sigma_r: Range between 0 to 1. - + :param shade_factor: Range between 0 to 0.1. @@ -63,14 +63,14 @@ stylization ----------- Stylization aims to produce digital imagery with a wide variety of effects not focused on photorealism. Edge-aware filters are ideal for stylization, as they can abstract regions of low contrast while preserving, or enhancing, high-contrast features. -.. ocv:function:: void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45); +.. ocv:function:: void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45) :param src: Input 8-bit 3-channel image. :param dst: Output image with the same size and type as ``src``. :param sigma_s: Range between 0 to 200. - + :param sigma_r: Range between 0 to 1. @@ -78,13 +78,12 @@ edgeEnhance ----------- Able to suppress low-amplitude details and enhance edges. -.. ocv:function:: void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45); +.. ocv:function:: void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45) :param src: Input 8-bit 3-channel image. :param dst: Output 8-bit 1-channel image. :param sigma_s: Range between 0 to 200. - - :param sigma_r: Range between 0 to 1. + :param sigma_r: Range between 0 to 1. diff --git a/modules/photo/doc/photo.rst b/modules/photo/doc/photo.rst index c8aefda99c..676f3e9d45 100644 --- a/modules/photo/doc/photo.rst +++ b/modules/photo/doc/photo.rst @@ -9,4 +9,7 @@ photo. Computational Photography inpainting denoising - hdr_imaging \ No newline at end of file + hdr_imaging + decolor + cloning + npr diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 1eb5ccaab1..1e83608800 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -47,51 +47,51 @@ #include "opencv2/imgproc.hpp" /*! \namespace cv - Namespace where all the C++ OpenCV functionality resides + Namespace where all the C++ OpenCV functionality resides */ namespace cv { -//! the inpainting algorithm -enum -{ - INPAINT_NS = 0, // Navier-Stokes algorithm - INPAINT_TELEA = 1 // A. Telea algorithm -}; + //! the inpainting algorithm + enum + { + INPAINT_NS = 0, // Navier-Stokes algorithm + INPAINT_TELEA = 1 // A. Telea algorithm + }; -enum -{ - NORMAL_CLONE = 1, - MIXED_CLONE = 2, - MONOCHROME_TRANSFER = 3 -}; + enum + { + NORMAL_CLONE = 1, + MIXED_CLONE = 2, + MONOCHROME_TRANSFER = 3 + }; -enum -{ - RECURS_FILTER = 1, - NORMCONV_FILTER = 2 -}; + enum + { + RECURS_FILTER = 1, + NORMCONV_FILTER = 2 + }; -//! restores the damaged image areas using one of the available intpainting algorithms -CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, - OutputArray dst, double inpaintRadius, int flags ); + //! restores the damaged image areas using one of the available intpainting algorithms + CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, + OutputArray dst, double inpaintRadius, int flags ); -CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3, - int templateWindowSize = 7, int searchWindowSize = 21); + CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3, + int templateWindowSize = 7, int searchWindowSize = 21); -CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst, - float h = 3, float hColor = 3, - int templateWindowSize = 7, int searchWindowSize = 21); + CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst, + float h = 3, float hColor = 3, + int templateWindowSize = 7, int searchWindowSize = 21); -CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst, - int imgToDenoiseIndex, int temporalWindowSize, - float h = 3, int templateWindowSize = 7, int searchWindowSize = 21); + CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst, + int imgToDenoiseIndex, int temporalWindowSize, + float h = 3, int templateWindowSize = 7, int searchWindowSize = 21); -CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst, - int imgToDenoiseIndex, int temporalWindowSize, - float h = 3, float hColor = 3, - int templateWindowSize = 7, int searchWindowSize = 21); + CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst, + int imgToDenoiseIndex, int temporalWindowSize, + float h = 3, float hColor = 3, + int templateWindowSize = 7, int searchWindowSize = 21); enum { LDR_SIZE = 256 }; @@ -301,35 +301,35 @@ public: CV_EXPORTS_W Ptr createMergeRobertson(); -CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost); + CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost); -CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, - OutputArray _blend, int flags); + CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, + OutputArray blend, int flags); -CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, - float green_mul = 1.0, float blue_mul = 1.0); + CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, + float green_mul = 1.0, float blue_mul = 1.0); -CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, - float alpha = 0.2, float beta = 0.4); + CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, + float alpha = 0.2, float beta = 0.4); -CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, - double low_threshold, double high_threshold, - int kernel_size); + CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, + double low_threshold, double high_threshold, + int kernel_size); -CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, - float sigma_s = 60, float sigma_r = 0.4); + CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, + float sigma_s = 60, float sigma_r = 0.4); -CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, - float sigma_r = 0.15); + CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, + float sigma_r = 0.15); -CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst, OutputArray dst1, - float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); + CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, + float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); -CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, - float sigma_r = 0.45); + CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, + float sigma_r = 0.45); -CV_EXPORTS_W void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, - float sigma_r = 0.45); + CV_EXPORTS_W void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, + float sigma_r = 0.45); } // cv diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 14ed6ac30f..56912199ea 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -42,8 +42,6 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" -#include "opencv2/imgproc.hpp" -#include #include "math.h" #include #include @@ -53,21 +51,21 @@ using namespace std; using namespace cv; -double norm(double); +double norm_m(double); -double norm(double E) +double norm_m(double E) { - return (sqrt(pow(E,2))); + return sqrt(pow(E,2)); } -void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) +void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) { Mat I = _src.getMat(); _dst.create(I.size(), CV_8UC1); Mat dst = _dst.getMat(); - _boost.create(I.size(), CV_8UC3); - Mat color_boost = _boost.getMat(); + _color_boost.create(I.size(), CV_8UC3); + Mat color_boost = _color_boost.getMat(); if(!I.data ) { @@ -82,7 +80,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) int maxIter = 15; int iterCount = 0; - float tol = .0001; + double tol = .0001; double E = 0; double pre_E = std::numeric_limits::infinity(); @@ -113,7 +111,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) //////////////////////////////// main loop starting //////////////////////////////////////// - while(norm(E-pre_E) > tol) + while(norm_m(E-pre_E) > tol) { iterCount +=1; pre_E = E; @@ -223,7 +221,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) for(int i =0;i(i,j) = 255.0*Gray.at(i,j); + l.at(i,j) = dst.at(i,j); } for(int i =0;i #include @@ -124,12 +123,12 @@ void Decolor::init() vector Decolor::product(vector < vector > &comb, vector &initRGB) { vector res; - float dp; + double dp; for (unsigned int i=0;i > &poly, vector (i,j) = poly[i][j]; + P.at(i,j) = (float) poly[i][j]; - Mat P_trans = P.t(); + Mat P_trans = P.t(); Mat B = Mat(poly.size(),poly[0].size(), CV_32FC1); for(unsigned int i =0;i < poly.size();i++) { for(unsigned int j=0;j(i,j) = poly[i][j]*Cg[j]; + B.at(i,j) = (float) (poly[i][j] * Cg[j]); } A = P*P_trans; @@ -486,14 +485,14 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int i = 0;i(i,j)=Gray.at(i,j) + - wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* + (float) wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* pow(blue.at(i,j),b); kk=kk+1; } - double minval = INT_MAX; - double maxval = INT_MIN; + float minval = INT_MAX; + float maxval = INT_MIN; for(int i=0;i #include @@ -54,215 +51,215 @@ using namespace cv; void cv::edgePreservingFilter(InputArray _src, OutputArray _dst, int flags, float sigma_s, float sigma_r) { - Mat I = _src.getMat(); - _dst.create(I.size(), CV_8UC3); - Mat dst = _dst.getMat(); + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC3); + Mat dst = _dst.getMat(); - int h = I.size().height; - int w = I.size().width; + int h = I.size().height; + int w = I.size().width; - Mat res = Mat(h,w,CV_32FC3); - dst.convertTo(res,CV_32FC3,1.0/255.0); + Mat res = Mat(h,w,CV_32FC3); + dst.convertTo(res,CV_32FC3,1.0/255.0); - Domain_Filter obj; + Domain_Filter obj; - Mat img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); - obj.filter(img, res, sigma_s, sigma_r, flags); + obj.filter(img, res, sigma_s, sigma_r, flags); - convertScaleAbs(res, dst, 255,0); + convertScaleAbs(res, dst, 255,0); } void cv::detailEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) { - Mat I = _src.getMat(); - _dst.create(I.size(), CV_8UC3); - Mat dst = _dst.getMat(); + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC3); + Mat dst = _dst.getMat(); - int h = I.size().height; - int w = I.size().width; - int channel = I.channels(); - float factor = 3.0; + int h = I.size().height; + int w = I.size().width; + int channel = I.channels(); + float factor = 3.0; - Mat img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); - - Mat res = Mat(h,w,CV_32FC3); - dst.convertTo(res,CV_32FC3,1.0/255.0); + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); - Mat result = Mat(img.size(),CV_32FC3); - Mat lab = Mat(img.size(),CV_32FC3); - Mat l_channel = Mat(img.size(),CV_32FC1); - Mat a_channel = Mat(img.size(),CV_32FC1); - Mat b_channel = Mat(img.size(),CV_32FC1); + Mat res = Mat(h,w,CV_32FC3); + dst.convertTo(res,CV_32FC3,1.0/255.0); - cvtColor(img,lab,COLOR_BGR2Lab); + Mat result = Mat(img.size(),CV_32FC3); + Mat lab = Mat(img.size(),CV_32FC3); + Mat l_channel = Mat(img.size(),CV_32FC1); + Mat a_channel = Mat(img.size(),CV_32FC1); + Mat b_channel = Mat(img.size(),CV_32FC1); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - { - l_channel.at(i,j) = lab.at(i,j*channel+0); - a_channel.at(i,j) = lab.at(i,j*channel+1); - b_channel.at(i,j) = lab.at(i,j*channel+2); - } + cvtColor(img,lab,COLOR_BGR2Lab); - Mat L = Mat(img.size(),CV_32FC1); + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + { + l_channel.at(i,j) = lab.at(i,j*channel+0); + a_channel.at(i,j) = lab.at(i,j*channel+1); + b_channel.at(i,j) = lab.at(i,j*channel+2); + } - l_channel.convertTo(L,CV_32FC1,1.0/255.0); + Mat L = Mat(img.size(),CV_32FC1); - Domain_Filter obj; + l_channel.convertTo(L,CV_32FC1,1.0/255.0); - obj.filter(L, res, sigma_s, sigma_r, 1); + Domain_Filter obj; - Mat detail = Mat(h,w,CV_32FC1); + obj.filter(L, res, sigma_s, sigma_r, 1); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - detail.at(i,j) = L.at(i,j) - res.at(i,j); + Mat detail = Mat(h,w,CV_32FC1); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - L.at(i,j) = res.at(i,j) + factor*detail.at(i,j); + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + detail.at(i,j) = L.at(i,j) - res.at(i,j); - L.convertTo(l_channel,CV_32FC1,255); + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + L.at(i,j) = res.at(i,j) + factor*detail.at(i,j); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - { - lab.at(i,j*channel+0) = l_channel.at(i,j); - lab.at(i,j*channel+1) = a_channel.at(i,j); - lab.at(i,j*channel+2) = b_channel.at(i,j); - } + L.convertTo(l_channel,CV_32FC1,255); - cvtColor(lab,result,COLOR_Lab2BGR); - result.convertTo(dst,CV_8UC3,255); + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + { + lab.at(i,j*channel+0) = l_channel.at(i,j); + lab.at(i,j*channel+1) = a_channel.at(i,j); + lab.at(i,j*channel+2) = b_channel.at(i,j); + } + + cvtColor(lab,result,COLOR_Lab2BGR); + result.convertTo(dst,CV_8UC3,255); } -void cv::pencilSketch(InputArray _src, OutputArray _dst, OutputArray _dst1, float sigma_s, float sigma_r, float shade_factor) +void cv::pencilSketch(InputArray _src, OutputArray _dst1, OutputArray _dst2, float sigma_s, float sigma_r, float shade_factor) { - Mat I = _src.getMat(); - _dst.create(I.size(), CV_8UC1); - Mat dst = _dst.getMat(); + Mat I = _src.getMat(); + _dst1.create(I.size(), CV_8UC1); + Mat dst1 = _dst1.getMat(); - _dst1.create(I.size(), CV_8UC3); - Mat dst1 = _dst1.getMat(); - - Mat img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); + _dst2.create(I.size(), CV_8UC3); + Mat dst2 = _dst2.getMat(); - Domain_Filter obj; + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); - Mat sketch = Mat(I.size(),CV_32FC1); - Mat color_sketch = Mat(I.size(),CV_32FC3); + Domain_Filter obj; - obj.pencil_sketch(img, sketch, color_sketch, sigma_s, sigma_r, shade_factor); + Mat sketch = Mat(I.size(),CV_32FC1); + Mat color_sketch = Mat(I.size(),CV_32FC3); - sketch.convertTo(dst,CV_8UC1,255); - color_sketch.convertTo(dst1,CV_8UC3,255); + obj.pencil_sketch(img, sketch, color_sketch, sigma_s, sigma_r, shade_factor); + + sketch.convertTo(dst1,CV_8UC1,255); + color_sketch.convertTo(dst2,CV_8UC3,255); } void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) { - Mat I = _src.getMat(); - _dst.create(I.size(), CV_8UC3); - Mat dst = _dst.getMat(); + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC3); + Mat dst = _dst.getMat(); - Mat img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); - int h = img.size().height; - int w = img.size().width; - int channel = img.channels(); + int h = img.size().height; + int w = img.size().width; + int channel = img.channels(); - Mat res = Mat(h,w,CV_32FC3); + Mat res = Mat(h,w,CV_32FC3); - Domain_Filter obj; - obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); + Domain_Filter obj; + obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); - vector planes; - split(res, planes); + vector planes; + split(res, planes); - Mat magXR = Mat(h, w, CV_32FC1); - Mat magYR = Mat(h, w, CV_32FC1); + Mat magXR = Mat(h, w, CV_32FC1); + Mat magYR = Mat(h, w, CV_32FC1); - Mat magXG = Mat(h, w, CV_32FC1); - Mat magYG = Mat(h, w, CV_32FC1); + Mat magXG = Mat(h, w, CV_32FC1); + Mat magYG = Mat(h, w, CV_32FC1); - Mat magXB = Mat(h, w, CV_32FC1); - Mat magYB = Mat(h, w, CV_32FC1); + Mat magXB = Mat(h, w, CV_32FC1); + Mat magYB = Mat(h, w, CV_32FC1); - Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); - Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); + Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); + Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); - Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); - Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); + Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); + Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); - Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); - Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); + Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); + Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); - Mat magx = Mat(h,w,CV_32FC1); - Mat magy = Mat(h,w,CV_32FC1); + Mat magx = Mat(h,w,CV_32FC1); + Mat magy = Mat(h,w,CV_32FC1); - Mat mag1 = Mat(h,w,CV_32FC1); - Mat mag2 = Mat(h,w,CV_32FC1); - Mat mag3 = Mat(h,w,CV_32FC1); + Mat mag1 = Mat(h,w,CV_32FC1); + Mat mag2 = Mat(h,w,CV_32FC1); + Mat mag3 = Mat(h,w,CV_32FC1); - magnitude(magXR,magYR,mag1); - magnitude(magXG,magYG,mag2); - magnitude(magXB,magYB,mag3); + magnitude(magXR,magYR,mag1); + magnitude(magXG,magYG,mag2); + magnitude(magXB,magYB,mag3); - Mat magnitude = Mat(h,w,CV_32FC1); + Mat magnitude = Mat(h,w,CV_32FC1); - for(int i =0;i < h;i++) - for(int j=0;j(i,j) = mag1.at(i,j) + mag2.at(i,j) + mag3.at(i,j); - } + for(int i =0;i < h;i++) + for(int j=0;j(i,j) = mag1.at(i,j) + mag2.at(i,j) + mag3.at(i,j); + } - for(int i =0;i < h;i++) - for(int j=0;j(i,j) = 1.0 - magnitude.at(i,j); - } + for(int i =0;i < h;i++) + for(int j=0;j(i,j) = 1.0f - magnitude.at(i,j); + } - Mat stylized = Mat(h,w,CV_32FC3); + Mat stylized = Mat(h,w,CV_32FC3); - for(int i =0;i < h;i++) - for(int j=0;j(i,j*channel + c) = res.at(i,j*channel + c) * magnitude.at(i,j); - } + for(int i =0;i < h;i++) + for(int j=0;j(i,j*channel + c) = res.at(i,j*channel + c) * magnitude.at(i,j); + } - stylized.convertTo(dst,CV_8UC3,255); + stylized.convertTo(dst,CV_8UC3,255); } void cv::edgeEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) { - Mat I = _src.getMat(); - _dst.create(I.size(), CV_8UC1); - Mat dst = _dst.getMat(); + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC1); + Mat dst = _dst.getMat(); - Mat img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); - Mat orig = img.clone(); + Mat orig = img.clone(); - int h = img.size().height; - int w = img.size().width; + int h = img.size().height; + int w = img.size().width; - Mat res = Mat(h,w,CV_32FC3); - Mat magnitude = Mat(h,w,CV_32FC1); + Mat res = Mat(h,w,CV_32FC3); + Mat magnitude = Mat(h,w,CV_32FC1); - Mat mag8 = Mat(h,w,CV_32FC1); + Mat mag8 = Mat(h,w,CV_32FC1); - Domain_Filter obj; + Domain_Filter obj; - obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); + obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); - obj.find_magnitude(res,magnitude); + obj.find_magnitude(res,magnitude); - magnitude.convertTo(dst,CV_8UC1,255); + magnitude.convertTo(dst,CV_8UC1,255); } diff --git a/modules/photo/src/npr.hpp b/modules/photo/src/npr.hpp index 66638ccbd8..3f5519d1bb 100644 --- a/modules/photo/src/npr.hpp +++ b/modules/photo/src/npr.hpp @@ -41,12 +41,12 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" -#include "opencv2/imgproc.hpp" #include #include #include #include "math.h" + using namespace std; using namespace cv; @@ -79,7 +79,7 @@ void Domain_Filter::diffx(const Mat &img, Mat &temp) { for(int c =0; c < channel; c++) { - temp.at(i,j*channel+c) = + temp.at(i,j*channel+c) = img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); } } @@ -94,7 +94,7 @@ void Domain_Filter::diffy(const Mat &img, Mat &temp) { for(int c =0; c < channel; c++) { - temp.at(i,j*channel+c) = + temp.at(i,j*channel+c) = img.at((i+1),j*channel+c) - img.at(i,j*channel+c); } } @@ -179,7 +179,7 @@ void Domain_Filter::find_magnitude(Mat &img, Mat &mag) for(int i =0;i < h;i++) for(int j=0;j(i,j) = 1.0 - mag.at(i,j); + mag.at(i,j) = 1.0f - mag.at(i,j); } } @@ -193,7 +193,7 @@ void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) int w = output.cols; int channel = output.channels(); - a = exp(-sqrt(2) / sigma_h); + a = (float) exp((-1.0 * sqrt(2.0)) / sigma_h); Mat temp = Mat(h,w,CV_32FC3); @@ -202,21 +202,19 @@ void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) for(int c=0;c(i,j*channel+c) = output.at(i,j*channel+c); - Mat V = Mat(h,w,CV_32FC1); for(int i=0;i(i,j) = pow(a,hz.at(i,j)); - for(int i=0; i(i,j*channel+c) = temp.at(i,j*channel+c) + + temp.at(i,j*channel+c) = temp.at(i,j*channel+c) + (temp.at(i,(j-1)*channel+c) - temp.at(i,j*channel+c)) * V.at(i,j); } } @@ -267,7 +265,7 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float { for(int j=0;j(0,j) = hz.at(i,j); - domain_row.at(0,w) = myinf; + domain_row.at(0,w) = (float) myinf; Mat lower_pos_row = Mat::zeros(1,w,CV_32FC1); Mat upper_pos_row = Mat::zeros(1,w,CV_32FC1); @@ -285,7 +283,7 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float { if(domain_row.at(0,j) > lower_pos_row.at(0,0)) { - temp_lower_idx.at(0,0) = j; + temp_lower_idx.at(0,0) = (float) j; break; } } @@ -293,7 +291,7 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float { if(domain_row.at(0,j) > upper_pos_row.at(0,0)) { - temp_upper_idx.at(0,0) = j; + temp_upper_idx.at(0,0) = (float) j; break; } } @@ -302,7 +300,7 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float for(int j=1;j(0,j-1);k(0,j-1);k(0,k) > lower_pos_row.at(0,j)) { @@ -315,7 +313,7 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float temp_lower_idx.at(0,j) = temp_lower_idx.at(0,j-1) + temp; count = 0; - for(int k=temp_upper_idx.at(0,j-1);k(0,j-1);k(i,j) = i+1; + indices.at(i,j) = (float) i+1; Mat a = Mat::zeros(h,w,CV_32FC1); Mat b = Mat::zeros(h,w,CV_32FC1); @@ -402,8 +400,8 @@ void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float r for(int j=0;j(i,j)/(h*(w+1)); - rem = b.at(i,j) - r*h*(w+1); + r = (int) b.at(i,j)/(h*(w+1)); + rem = (int) b.at(i,j) - r*h*(w+1); q = rem/h; p = rem - q*h; if(q==0) @@ -419,8 +417,8 @@ void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float r } - r1 = a.at(i,j)/(h*(w+1)); - rem1 = a.at(i,j) - r1*h*(w+1); + r1 = (int) a.at(i,j)/(h*(w+1)); + rem1 = (int) a.at(i,j) - r1*h*(w+1); q1 = rem1/h; p1 = rem1 - q1*h; if(p1==0) @@ -465,7 +463,7 @@ void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r for(int j = 0,k=1; j < w-1; j++,k++) for(int c = 0; c < channel; c++) { - distx.at(i,k) = + distx.at(i,k) = distx.at(i,k) + abs(derivx.at(i,j*channel+c)); } @@ -473,7 +471,7 @@ void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r for(int j = 0; j < w; j++) for(int c = 0; c < channel; c++) { - disty.at(k,j) = + disty.at(k,j) = disty.at(k,j) + abs(derivy.at(i,j*channel+c)); } @@ -539,11 +537,11 @@ void Domain_Filter::filter(const Mat &img, Mat &res, float sigma_s = 60, float s if(flags == 1) { - Mat vert_t = vert.t(); + Mat vert_t = vert.t(); for(int i=0;i #include @@ -243,4 +240,3 @@ void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst, Cloning obj; obj.texture_flatten(src,cs_mask,gray,low_threshold,high_threshold,kernel_size,blend); } - diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index f039d2974d..b000e1a303 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -41,9 +41,6 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" -#include "opencv2/core.hpp" #include #include #include @@ -162,7 +159,7 @@ void Cloning::dst(double *gtest, double *gfinal,int h,int w) for(int j=0,r=1;j(r,0) = gtest[idx]; + temp.at(r,0) = (float) gtest[idx]; } temp.at(h+1,0)=0.0; @@ -170,7 +167,7 @@ void Cloning::dst(double *gtest, double *gfinal,int h,int w) for(int j=h-1, r=h+2;j>=0;j--,r++) { idx = j*w+i; - temp.at(r,0) = -1*gtest[idx]; + temp.at(r,0) = (float) (-1.0 * gtest[idx]); } merge(planes, 2, complex1); @@ -179,7 +176,7 @@ void Cloning::dst(double *gtest, double *gfinal,int h,int w) Mat planes1[] = {Mat::zeros(complex1.size(), CV_32F), Mat::zeros(complex1.size(), CV_32F)}; - split(complex1, planes1); + split(complex1, planes1); std::complex two_i = std::sqrt(std::complex(-1)); @@ -187,7 +184,7 @@ void Cloning::dst(double *gtest, double *gfinal,int h,int w) for(int c=1,z=0;c(z,0) = planes1[1].at(c,0)/fac; + res.at(z,0) = (float) (planes1[1].at(c,0)/fac); } for(int q=0,z=0;q(i,j) = mat[idx]; + tmp.at(i,j) = (float) mat[idx]; } } Mat tmp_t = tmp.t(); @@ -264,7 +261,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) for(int i =1;i(i,j) = 0.0; + bound.at(i,j) = 0; } double *f_bp = new double[h*w]; @@ -284,7 +281,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) for(int j=0;j(i,j) = (lap.at(i,j) - f_bp[idx]); + diff.at(i,j) = (float) (lap.at(i,j) - f_bp[idx]); } } @@ -336,7 +333,6 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) gfinal_t[idx] = gfinal_t[idx]/denom[idx]; } - idst(gfinal_t,f3,h-2,w-2); transpose(f3,f3_t,h-2,w-2); @@ -350,7 +346,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) for(int j = 0 ; j < w; j++) { idx = i*w + j; - img_d[idx] = (double)img.at(i,j); + img_d[idx] = (double)img.at(i,j); } } for(int i = 1 ; i < h-1;i++) @@ -358,7 +354,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) for(int j = 1 ; j < w-1; j++) { idx = i*w + j; - img_d[idx] = 0.0; + img_d[idx] = 0.0; } } for(int i = 1,id1=0 ; i < h-1;i++,id1++) @@ -367,7 +363,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) { idx = i*w + j; idx1= id1*(w-2) + id2; - img_d[idx] = f3_t[idx1]; + img_d[idx] = f3_t[idx1]; } } @@ -379,9 +375,9 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) if(img_d[idx] < 0.0) result.at(i,j) = 0; else if(img_d[idx] > 255.0) - result.at(i,j) = 255.0; + result.at(i,j) = 255; else - result.at(i,j) = img_d[idx]; + result.at(i,j) = (uchar) img_d[idx]; } } @@ -410,8 +406,8 @@ void Cloning::init(Mat &I, Mat &wmask) for(int i=0;i(i,j) = I.at(i,j*3+0); - g_channel.at(i,j) = I.at(i,j*3+1); + r_channel.at(i,j) = I.at(i,j*3+0); + g_channel.at(i,j) = I.at(i,j*3+1); b_channel.at(i,j) = I.at(i,j*3+2); } @@ -453,8 +449,8 @@ void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) for(int i=0;i(i,j) = gxx.at(i,j*3+0); - gx_channel.at(i,j) = gxx.at(i,j*3+1); + rx_channel.at(i,j) = gxx.at(i,j*3+0); + gx_channel.at(i,j) = gxx.at(i,j*3+1); bx_channel.at(i,j) = gxx.at(i,j*3+2); } @@ -465,8 +461,8 @@ void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) for(int i=0;i(i,j) = gyy.at(i,j*3+0); - gy_channel.at(i,j) = gyy.at(i,j*3+1); + ry_channel.at(i,j) = gyy.at(i,j*3+0); + gy_channel.at(i,j) = gyy.at(i,j*3+1); by_channel.at(i,j) = gyy.at(i,j*3+2); } @@ -474,18 +470,10 @@ void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) resultg = Mat(I.size(),CV_8UC1); resultb = Mat(I.size(),CV_8UC1); - clock_t tic = clock(); - - poisson_solver(r_channel,rx_channel, ry_channel,resultr); poisson_solver(g_channel,gx_channel, gy_channel,resultg); poisson_solver(b_channel,bx_channel, by_channel,resultb); - clock_t toc = clock(); - - printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); - - } void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num) @@ -562,8 +550,8 @@ void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num) for(int i=0;i(i,j*3+0) = gray.at(i,j); - gray8.at(i,j*3+1) = gray.at(i,j); + gray8.at(i,j*3+0) = gray.at(i,j); + gray8.at(i,j*3+1) = gray.at(i,j); gray8.at(i,j*3+2) = gray.at(i,j); } diff --git a/modules/photo/test/test_cloning.cpp b/modules/photo/test/test_cloning.cpp index e6fbf3e6a3..761b6e0d70 100644 --- a/modules/photo/test/test_cloning.cpp +++ b/modules/photo/test/test_cloning.cpp @@ -125,7 +125,7 @@ TEST(Photo_SeamlessClone_featureExchange, regression) TEST(Photo_SeamlessClone_colorChange, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Color_Change/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/color_change/"; string original_path1 = folder + "source1.png"; string original_path2 = folder + "mask.png"; @@ -179,4 +179,3 @@ TEST(Photo_SeamlessClone_textureFlattening, regression) imwrite(folder + "cloned.png", result); } - diff --git a/modules/photo/test/test_decolor.cpp b/modules/photo/test/test_decolor.cpp index c218c6a4fa..bf21f37384 100644 --- a/modules/photo/test/test_decolor.cpp +++ b/modules/photo/test/test_decolor.cpp @@ -65,4 +65,3 @@ TEST(Photo_Decolor, regression) imwrite(folder + "color_boost.png",color_boost); } - diff --git a/modules/photo/test/test_npr.cpp b/modules/photo/test/test_npr.cpp index 0a4b2c56ef..5d55d4c3b4 100644 --- a/modules/photo/test/test_npr.cpp +++ b/modules/photo/test/test_npr.cpp @@ -50,7 +50,7 @@ using namespace std; TEST(Photo_NPR_EdgePreserveSmoothing_RecursiveFilter, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Smoothing/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; string original_path = folder + "test1.png"; Mat source = imread(original_path, IMREAD_COLOR); @@ -66,7 +66,7 @@ TEST(Photo_NPR_EdgePreserveSmoothing_RecursiveFilter, regression) TEST(Photo_NPR_EdgePreserveSmoothing_NormConvFilter, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Smoothing/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; string original_path = folder + "test1.png"; Mat source = imread(original_path, IMREAD_COLOR); @@ -82,7 +82,7 @@ TEST(Photo_NPR_EdgePreserveSmoothing_NormConvFilter, regression) TEST(Photo_NPR_DetailEnhance, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Detail_Enhance/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; string original_path = folder + "test1.png"; Mat source = imread(original_path, IMREAD_COLOR); @@ -98,7 +98,7 @@ TEST(Photo_NPR_DetailEnhance, regression) TEST(Photo_NPR_PencilSketch, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Pencil_Sketch/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; string original_path = folder + "test1.png"; Mat source = imread(original_path, IMREAD_COLOR); @@ -115,7 +115,7 @@ TEST(Photo_NPR_PencilSketch, regression) TEST(Photo_NPR_Stylization, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Stylization/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; string original_path = folder + "test1.png"; Mat source = imread(original_path, IMREAD_COLOR); @@ -131,7 +131,7 @@ TEST(Photo_NPR_Stylization, regression) TEST(Photo_NPR_EdgeEnhance, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Edge_Enhance/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; string original_path = folder + "test1.png"; Mat source = imread(original_path, IMREAD_COLOR); diff --git a/samples/cpp/cloning_demo.cpp b/samples/cpp/cloning_demo.cpp index 1992b65e98..d9bcfb3eb6 100644 --- a/samples/cpp/cloning_demo.cpp +++ b/samples/cpp/cloning_demo.cpp @@ -46,14 +46,14 @@ int main() int num; cin >> num; cout << endl; - + if(num == 1) { string folder = "cloning/Normal_Cloning/"; string original_path1 = folder + "source1.png"; string original_path2 = folder + "destination1.png"; string original_path3 = folder + "mask.png"; - + Mat source = imread(original_path1, IMREAD_COLOR); Mat destination = imread(original_path2, IMREAD_COLOR); Mat mask = imread(original_path3, IMREAD_COLOR); @@ -63,7 +63,7 @@ int main() cout << "Could not load source image " << original_path1 << endl; exit(0); } - if(destination.empty()) + if(destination.empty()) { cout << "Could not load destination image " << original_path2 << endl; exit(0); @@ -78,24 +78,24 @@ int main() Point p; p.x = 400; p.y = 100; - + seamlessClone(source, destination, mask, p, result, 1); - + imshow("Output",result); imwrite(folder + "cloned.png", result); } else if(num == 2) - { + { string folder = "cloning/Mixed_Cloning/"; string original_path1 = folder + "source1.png"; string original_path2 = folder + "destination1.png"; string original_path3 = folder + "mask.png"; - + Mat source = imread(original_path1, IMREAD_COLOR); Mat destination = imread(original_path2, IMREAD_COLOR); Mat mask = imread(original_path3, IMREAD_COLOR); - if(source.empty()) + if(source.empty()) { cout << "Could not load source image " << original_path1 << endl; exit(0); @@ -105,7 +105,7 @@ int main() cout << "Could not load destination image " << original_path2 << endl; exit(0); } - if(mask.empty()) + if(mask.empty()) { cout << "Could not load mask image " << original_path3 << endl; exit(0); @@ -115,7 +115,7 @@ int main() Point p; p.x = destination.size().width/2; p.y = destination.size().height/2; - + seamlessClone(source, destination, mask, p, result, 2); imshow("Output",result); @@ -137,12 +137,12 @@ int main() cout << "Could not load source image " << original_path1 << endl; exit(0); } - if(destination.empty()) + if(destination.empty()) { cout << "Could not load destination image " << original_path2 << endl; exit(0); } - if(mask.empty()) + if(mask.empty()) { cout << "Could not load mask image " << original_path3 << endl; exit(0); @@ -152,7 +152,7 @@ int main() Point p; p.x = destination.size().width/2; p.y = destination.size().height/2; - + seamlessClone(source, destination, mask, p, result, 3); imshow("Output",result); @@ -179,7 +179,7 @@ int main() } Mat result; - + colorChange(source, mask, result, 1.5, .5, .5); imshow("Output",result); @@ -194,7 +194,7 @@ int main() Mat source = imread(original_path1, IMREAD_COLOR); Mat mask = imread(original_path2, IMREAD_COLOR); - if(source.empty()) + if(source.empty()) { cout << "Could not load source image " << original_path1 << endl; exit(0); @@ -206,7 +206,7 @@ int main() } Mat result; - + illuminationChange(source, mask, result, .2, .4); imshow("Output",result); @@ -233,7 +233,7 @@ int main() } Mat result; - + textureFlattening(source, mask, result, 30, 45, 3); imshow("Output",result); diff --git a/samples/cpp/cloning_gui.cpp b/samples/cpp/cloning_gui.cpp index 4ba6b61dad..2457b12154 100644 --- a/samples/cpp/cloning_gui.cpp +++ b/samples/cpp/cloning_gui.cpp @@ -52,9 +52,6 @@ Point* pts = new Point[100]; Point* pts2 = new Point[100]; Point* pts_diff = new Point[100]; -char src[50]; -char dest[50]; - int var = 0; int flag = 0, flag1 = 0, flag4 = 0; @@ -76,39 +73,38 @@ void checkfile(char*); void source(int event, int x, int y, int, void*) { - if (event == EVENT_LBUTTONDOWN && !drag) - { - if(flag1 == 0) - { - if(var==0) - img1 = img0.clone(); - point = Point(x, y); - circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); - pts[var] = point; - var++; - drag = 1; - if(var>1) - line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); + if (event == EVENT_LBUTTONDOWN && !drag) + { + if(flag1 == 0) + { + if(var==0) + img1 = img0.clone(); + point = Point(x, y); + circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); + pts[var] = point; + var++; + drag = 1; + if(var>1) + line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); - imshow("Source", img1); - } - } + imshow("Source", img1); + } + } + if (event == EVENT_LBUTTONUP && drag) + { + imshow("Source", img1); - if (event == EVENT_LBUTTONUP && drag) - { - imshow("Source", img1); + drag = 0; + } + if (event == EVENT_RBUTTONDOWN) + { + flag1 = 1; + img1 = img0.clone(); + for(int i = var; i < numpts ; i++) + pts[i] = point; - drag = 0; - } - if (event == EVENT_RBUTTONDOWN) - { - flag1 = 1; - img1 = img0.clone(); - for(int i = var; i < numpts ; i++) - pts[i] = point; - - if(var!=0) + if(var!=0) { const Point* pts3[1] = {&pts[0]}; polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); @@ -169,67 +165,67 @@ void source(int event, int x, int y, int, void*) waitKey(0); } - } - if (event == EVENT_MBUTTONDOWN) - { - for(int i = 0; i < numpts ; i++) - { - pts[i].x=0; - pts[i].y=0; - } - var = 0; - flag1 = 0; - minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; - imshow("Source", img0); + } + if (event == EVENT_MBUTTONDOWN) + { + for(int i = 0; i < numpts ; i++) + { + pts[i].x=0; + pts[i].y=0; + } + var = 0; + flag1 = 0; + minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + imshow("Source", img0); if(num == 1 || num == 2 || num == 3) imshow("Destination",img2); - drag = 0; - } + drag = 0; + } } void destination(int event, int x, int y, int, void*) { - Mat im1; - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; - im1 = img2.clone(); - if (event == EVENT_LBUTTONDOWN) - { + Mat im1; + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + im1 = img2.clone(); + if (event == EVENT_LBUTTONDOWN) + { flag4 = 1; - if(flag1 == 1) - { - point = Point(x, y); + if(flag1 == 1) + { + point = Point(x, y); for(int i=0;i im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0) { @@ -254,7 +250,7 @@ void destination(int event, int x, int y, int, void*) if(num == 1 || num == 2 || num == 3) { - seamlessClone(img0,img2,res1,point,blend,num); + seamlessClone(img0,img2,res1,point,blend,num); imshow("Cloned Image", blend); imwrite("cloned.png",blend); waitKey(0); @@ -302,25 +298,24 @@ int main() cin >> num; cout << endl; - char s[]="Source"; - char d[]="Destination"; - minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + int flag3 = 0; + if(num == 1 || num == 2 || num == 3) { string src,dest; cout << "Enter Source Image: "; cin >> src; - + cout << "Enter Destination Image: "; cin >> dest; img0 = imread(src); - + img2 = imread(dest); if(!img0.data) @@ -333,7 +328,7 @@ int main() cout << "Destination Image does not exist" << endl; exit(0); } - + channel = img0.channels(); res = Mat::zeros(img2.size(),CV_8UC1); @@ -358,7 +353,7 @@ int main() string src; cout << "Enter Source Image: "; cin >> src; - + cout << "Enter RGB values: " << endl; cout << "Red: "; cin >> red; @@ -428,10 +423,10 @@ int main() cout << "high_threshold: "; cin >> high_t; - + cout << "kernel_size: "; cin >> kernel_size; - + img0 = imread(src); if(!img0.data) @@ -439,7 +434,7 @@ int main() cout << "Source Image does not exist" << endl; exit(0); } - + res1 = Mat::zeros(img0.size(),CV_8UC1); final = Mat::zeros(img0.size(),CV_8UC3); @@ -449,12 +444,15 @@ int main() setMouseCallback("Source", source, NULL); imshow("Source", img0); } - - int flag3 = 0; - - while(true) + else { - char key = waitKey(0); + cout << "Wrong Option Choosen" << endl; + exit(0); + } + + for(;;) + { + char key = (char) waitKey(0); if(key == 'd' && flag3 == 0) { diff --git a/samples/cpp/create_mask.cpp b/samples/cpp/create_mask.cpp index 59905f1403..6da64d738f 100644 --- a/samples/cpp/create_mask.cpp +++ b/samples/cpp/create_mask.cpp @@ -1,4 +1,4 @@ - /* +/* * create_mask.cpp * * Author: @@ -9,8 +9,6 @@ * mask image. */ - - #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" #include "opencv2/core.hpp" @@ -41,86 +39,85 @@ void mouseHandler(int, int, int, int, void*); void mouseHandler(int event, int x, int y, int, void*) { - if (event == EVENT_LBUTTONDOWN && !drag) - { - if(flag1 == 0) - { - if(var==0) - img1 = img0.clone(); - point = Point(x, y); - circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); - pts[var] = point; - var++; - drag = 1; - if(var>1) - line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); + if (event == EVENT_LBUTTONDOWN && !drag) + { + if(flag1 == 0) + { + if(var==0) + img1 = img0.clone(); + point = Point(x, y); + circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); + pts[var] = point; + var++; + drag = 1; + if(var>1) + line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); - imshow("Source", img1); - } - } + imshow("Source", img1); + } + } + if (event == EVENT_LBUTTONUP && drag) + { + imshow("Source", img1); - if (event == EVENT_LBUTTONUP && drag) - { - imshow("Source", img1); + drag = 0; + } + if (event == EVENT_RBUTTONDOWN) + { + flag1 = 1; + img1 = img0.clone(); + for(int i = var; i < numpts ; i++) + pts[i] = point; - drag = 0; - } - if (event == EVENT_RBUTTONDOWN) - { - flag1 = 1; - img1 = img0.clone(); - for(int i = var; i < numpts ; i++) - pts[i] = point; + if(var!=0) + { + const Point* pts3[1] = {&pts[0]}; + polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); + } - if(var!=0) - { - const Point* pts3[1] = {&pts[0]}; - polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); - } + for(int i=0;i Date: Tue, 1 Oct 2013 18:35:53 +0530 Subject: [PATCH 32/97] Changed STL in contrast_preserve file --- modules/photo/src/contrast_preserve.cpp | 6 ++-- modules/photo/src/contrast_preserve.hpp | 42 +++++++++++++++++++++---- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 56912199ea..103322a1b2 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -55,7 +55,7 @@ double norm_m(double); double norm_m(double E) { - return sqrt(pow(E,2)); + return sqroot(power(E,2)); } void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) @@ -136,8 +136,8 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) double ans1 = 0.0; for(unsigned int i =0;i &Cg, vector < vector > &polyGrad, vector &wei) @@ -99,7 +129,7 @@ double Decolor::energyCalcu(vector &Cg, vector < vector > &pol } for(unsigned int i=0;i &Cg) double res =0.0; for(unsigned int i=0;i > &polyGrad, for(int i = 0;i(i,j)= - pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); + power(red.at(i,j),r)*power(green.at(i,j),g)* + power(blue.at(i,j),b); vector curGrad; gradvector(curIm,curGrad); add_to_vector_poly(polyGrad,curGrad); @@ -485,8 +515,8 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int i = 0;i(i,j)=Gray.at(i,j) + - (float) wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); + (float) wei[kk]*power(red.at(i,j),r)*power(green.at(i,j),g)* + power(blue.at(i,j),b); kk=kk+1; } From 6c7272bde1a8ecc2cd00203116576bb3f2fa5152 Mon Sep 17 00:00:00 2001 From: siddharth Date: Tue, 1 Oct 2013 20:22:10 +0530 Subject: [PATCH 33/97] Update to remove Android error --- modules/photo/src/contrast_preserve.cpp | 2 +- modules/photo/src/contrast_preserve.hpp | 2 +- modules/photo/src/seamless_cloning.hpp | 18 +++++++++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 103322a1b2..9c7227405d 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -55,7 +55,7 @@ double norm_m(double); double norm_m(double E) { - return sqroot(power(E,2)); + return sqrt(power(E,2)); } void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index eff1530df5..587e431e08 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -235,7 +235,7 @@ void Decolor::colorGrad(Mat img, vector &Cg) double res =0.0; for(unsigned int i=0;i(i,j*channel+c) = - sqrt(pow(srx32.at(i,j*channel+c),2) + pow(sry32.at(i,j*channel+c),2)); + sqrt(power(srx32.at(i,j*channel+c),2) + power(sry32.at(i,j*channel+c),2)); } for(int i=0;i < h; i++) @@ -738,9 +750,9 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alph if(srx32.at(i,j*channel+c) != 0) { srx32.at(i,j*channel+c) = - pow(alpha,beta)*srx32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); + power(alpha,beta)*srx32.at(i,j*channel+c)*power(mag.at(i,j*channel+c),-1*beta); sry32.at(i,j*channel+c) = - pow(alpha,beta)*sry32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); + power(alpha,beta)*sry32.at(i,j*channel+c)*power(mag.at(i,j*channel+c),-1*beta); } } From 94eab9babe652e753bcb15bdeec65d6b6061eee8 Mon Sep 17 00:00:00 2001 From: siddharth Date: Tue, 1 Oct 2013 21:13:41 +0530 Subject: [PATCH 34/97] Revert Back --- modules/photo/src/contrast_preserve.cpp | 6 ++-- modules/photo/src/contrast_preserve.hpp | 42 ++++--------------------- modules/photo/src/seamless_cloning.hpp | 18 ++--------- 3 files changed, 12 insertions(+), 54 deletions(-) diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 9c7227405d..56912199ea 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -55,7 +55,7 @@ double norm_m(double); double norm_m(double E) { - return sqrt(power(E,2)); + return sqrt(pow(E,2)); } void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) @@ -136,8 +136,8 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) double ans1 = 0.0; for(unsigned int i =0;i &Cg, vector < vector > &polyGrad, vector &wei) @@ -129,7 +99,7 @@ double Decolor::energyCalcu(vector &Cg, vector < vector > &pol } for(unsigned int i=0;i &Cg) double res =0.0; for(unsigned int i=0;i > &polyGrad, for(int i = 0;i(i,j)= - power(red.at(i,j),r)*power(green.at(i,j),g)* - power(blue.at(i,j),b); + pow(red.at(i,j),r)*pow(green.at(i,j),g)* + pow(blue.at(i,j),b); vector curGrad; gradvector(curIm,curGrad); add_to_vector_poly(polyGrad,curGrad); @@ -515,8 +485,8 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int i = 0;i(i,j)=Gray.at(i,j) + - (float) wei[kk]*power(red.at(i,j),r)*power(green.at(i,j),g)* - power(blue.at(i,j),b); + (float) wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* + pow(blue.at(i,j),b); kk=kk+1; } diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index 1f92d933be..b000e1a303 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -75,18 +75,6 @@ class Cloning void texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, double high_threhold, int kernel_size, Mat &final); }; -double power(double term, int p); - -double power(double term, int p) -{ - double res = 1.0; - for(int i=0;i(i,j*channel+c) = - sqrt(power(srx32.at(i,j*channel+c),2) + power(sry32.at(i,j*channel+c),2)); + sqrt(pow(srx32.at(i,j*channel+c),2) + pow(sry32.at(i,j*channel+c),2)); } for(int i=0;i < h; i++) @@ -750,9 +738,9 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alph if(srx32.at(i,j*channel+c) != 0) { srx32.at(i,j*channel+c) = - power(alpha,beta)*srx32.at(i,j*channel+c)*power(mag.at(i,j*channel+c),-1*beta); + pow(alpha,beta)*srx32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); sry32.at(i,j*channel+c) = - power(alpha,beta)*sry32.at(i,j*channel+c)*power(mag.at(i,j*channel+c),-1*beta); + pow(alpha,beta)*sry32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); } } From daa9694cab2299d0168505d7f781497f9978059f Mon Sep 17 00:00:00 2001 From: siddharth Date: Mon, 7 Oct 2013 19:30:13 +0530 Subject: [PATCH 35/97] Changes done in decolorization module --- modules/photo/src/contrast_preserve.cpp | 46 ++---- modules/photo/src/contrast_preserve.hpp | 190 +++++++----------------- 2 files changed, 61 insertions(+), 175 deletions(-) diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 56912199ea..c60e7184b9 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -51,13 +51,6 @@ using namespace std; using namespace cv; -double norm_m(double); - -double norm_m(double E) -{ - return sqrt(pow(E,2)); -} - void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) { Mat I = _src.getMat(); @@ -78,6 +71,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) return; } + // Parameter Setting int maxIter = 15; int iterCount = 0; double tol = .0001; @@ -91,11 +85,11 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) img = Mat(I.size(),CV_32FC3); I.convertTo(img,CV_32FC3,1.0/255.0); + // Initialization obj.init(); vector Cg; vector < vector > polyGrad; - vector < vector > bc; vector < vector < int > > comb; vector alf; @@ -103,6 +97,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) obj.grad_system(img,polyGrad,Cg,comb); obj.weak_order(img,alf); + // Solver Mat Mt = Mat(polyGrad.size(),polyGrad[0].size(), CV_32FC1); obj.wei_update_matrix(polyGrad,Cg,Mt); @@ -111,7 +106,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) //////////////////////////////// main loop starting //////////////////////////////////////// - while(norm_m(E-pre_E) > tol) + while(sqrt(pow(E-pre_E,2)) > tol) { iterCount +=1; pre_E = E; @@ -136,8 +131,8 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) double ans1 = 0.0; for(unsigned int i =0;i lab_channel; + split(lab,lab_channel); - for(int i =0;i(i,j) = lab.at(i,j*3+0); - a.at(i,j) = lab.at(i,j*3+1); - b.at(i,j) = lab.at(i,j*3+2); - } + dst.copyTo(lab_channel[0]); - for(int i =0;i(i,j) = dst.at(i,j); - } - - for(int i =0;i(i,j*3+0) = l.at(i,j); - lab.at(i,j*3+1) = a.at(i,j); - lab.at(i,j*3+2) = b.at(i,j); - } + merge(lab_channel,lab); cvtColor(lab,color_boost,COLOR_Lab2BGR); } diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 87e33a38c9..6319d15513 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -51,11 +51,12 @@ using namespace cv; class Decolor { private: - Mat kernel; - Mat kernel1; + Mat kernelx; + Mat kernely; int order; public: + float sigma; void init(); vector product(vector < vector > &comb, vector &initRGB); double energyCalcu(vector &Cg, vector < vector > &polyGrad, vector &wei); @@ -73,18 +74,9 @@ class Decolor void grayImContruct(vector &wei, Mat img, Mat &Gray); }; -int rounding(double a); - -int rounding(double a) -{ - return int(a + 0.5); -} - -float sigma = .02; - double Decolor::energyCalcu(vector &Cg, vector < vector > &polyGrad, vector &wei) { - vector P; + vector energy; vector temp; vector temp1; @@ -99,11 +91,11 @@ double Decolor::energyCalcu(vector &Cg, vector < vector > &pol } for(unsigned int i=0;i &Cg, vector < vector > &pol void Decolor::init() { - kernel = Mat(1,2, CV_32FC1); - kernel1 = Mat(2,1, CV_32FC1); - kernel.at(0,0)=1.0; - kernel.at(0,1)=-1.0; - kernel1.at(0,0)=1.0; - kernel1.at(1,0)=-1.0; + kernelx = Mat(1,2, CV_32FC1); + kernely = Mat(2,1, CV_32FC1); + kernelx.at(0,0)=1.0; + kernelx.at(0,1)=-1.0; + kernely.at(0,0)=1.0; + kernely.at(1,0)=-1.0; order = 2; + sigma = .02; } vector Decolor::product(vector < vector > &comb, vector &initRGB) @@ -138,8 +131,8 @@ void Decolor::singleChannelGradx(const Mat &img, Mat& dest) { int w=img.size().width; int h=img.size().height; - Point anchor(kernel.cols - kernel.cols/2 - 1, kernel.rows - kernel.rows/2 - 1); - filter2D(img, dest, -1, kernel, anchor, 0.0, BORDER_CONSTANT); + Point anchor(kernelx.cols - kernelx.cols/2 - 1, kernelx.rows - kernelx.rows/2 - 1); + filter2D(img, dest, -1, kernelx, anchor, 0.0, BORDER_CONSTANT); for(int i=0;i(i,w-1)=0.0; } @@ -148,8 +141,8 @@ void Decolor::singleChannelGrady(const Mat &img, Mat& dest) { int w=img.size().width; int h=img.size().height; - Point anchor(kernel1.cols - kernel1.cols/2 - 1, kernel1.rows - kernel1.rows/2 - 1); - filter2D(img, dest, -1, kernel1, anchor, 0.0, BORDER_CONSTANT); + Point anchor(kernely.cols - kernely.cols/2 - 1, kernely.rows - kernely.rows/2 - 1); + filter2D(img, dest, -1, kernely, anchor, 0.0, BORDER_CONSTANT); for(int j=0;j(h-1,j)=0.0; } @@ -182,25 +175,19 @@ void Decolor::colorGrad(Mat img, vector &Cg) { Mat lab = Mat(img.size(),CV_32FC3); - Mat l_channel = Mat(img.size(),CV_32FC1); - Mat a_channel = Mat(img.size(),CV_32FC1); - Mat b_channel = Mat(img.size(),CV_32FC1); cvtColor(img,lab,COLOR_BGR2Lab); - for(int i=0;i(i,j) = lab.at(i,j*3+0); - a_channel.at(i,j) = lab.at(i,j*3+1); - b_channel.at(i,j) = lab.at(i,j*3+2); - } + + vector lab_channel; + split(lab,lab_channel); vector ImL; vector Ima; vector Imb; - gradvector(l_channel,ImL); - gradvector(a_channel,Ima); - gradvector(b_channel,Imb); + + gradvector(lab_channel[0],ImL); + gradvector(lab_channel[1],Ima); + gradvector(lab_channel[2],Imb); double res =0.0; for(unsigned int i=0;i &Cg) res=sqrt(pow(ImL[i],2) + pow(Ima[i],2) + pow(Imb[i],2))/100; Cg.push_back(res); } - lab.release(); - l_channel.release(); - a_channel.release(); - b_channel.release(); ImL.clear(); Ima.clear(); @@ -245,37 +228,20 @@ void Decolor::weak_order(Mat img, vector &alf) if((h + w) > 800) { sizefactor = (double)800/(h+w); - resize(img,img,Size(rounding(h*sizefactor),rounding(w*sizefactor))); + resize(img,img,Size(round(h*sizefactor),round(w*sizefactor))); } Mat curIm = Mat(img.size(),CV_32FC1); - Mat red = Mat(img.size(),CV_32FC1); - Mat green = Mat(img.size(),CV_32FC1); - Mat blue = Mat(img.size(),CV_32FC1); + vector rgb_channel; + split(img,rgb_channel); - for(int i=0;i(i,j) = img.at(i,j*3+2); - green.at(i,j) = img.at(i,j*3+1); - blue.at(i,j) = img.at(i,j*3+0); - } + vector Rg, Gg, Bg; + vector t1, t2, t3; + vector tmp1, tmp2, tmp3; - vector Rg; - vector Gg; - vector Bg; - - vector t1; - vector t2; - vector t3; - - vector tmp1; - vector tmp2; - vector tmp3; - - gradvector(red,Rg); - gradvector(green,Gg); - gradvector(blue,Bg); + gradvector(rgb_channel[2],Rg); + gradvector(rgb_channel[1],Gg); + gradvector(rgb_channel[0],Bg); double level = .05; @@ -285,37 +251,27 @@ void Decolor::weak_order(Mat img, vector &alf) t1.push_back(1.0); else t1.push_back(0.0); - } - for(unsigned int i=0;i level) t2.push_back(1.0); else t2.push_back(0.0); - } - for(unsigned int i=0;i level) t3.push_back(1.0); else t3.push_back(0.0); - } - for(unsigned int i=0;i &alf) sum = (double)100*sum/alf.size(); - red.release(); - green.release(); - blue.release(); - curIm.release(); - - Rg.clear(); - Gg.clear(); - Bg.clear(); - - t1.clear(); - t2.clear(); - t3.clear(); - - tmp1.clear(); - tmp2.clear(); - tmp3.clear(); + Rg.clear(); Gg.clear(); Bg.clear(); + t1.clear(); t2.clear(); t3.clear(); + tmp1.clear(); tmp2.clear(); tmp3.clear(); } void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, @@ -361,7 +304,7 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, if((h + w) > 800) { sizefactor = (double)800/(h+w); - resize(img,img,Size(rounding(h*sizefactor),rounding(w*sizefactor))); + resize(img,img,Size(round(h*sizefactor),round(w*sizefactor))); } h = img.size().height; @@ -369,17 +312,8 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, colorGrad(img,Cg); Mat curIm = Mat(img.size(),CV_32FC1); - Mat red = Mat(img.size(),CV_32FC1); - Mat green = Mat(img.size(),CV_32FC1); - Mat blue = Mat(img.size(),CV_32FC1); - - for(int i=0;i(i,j) = img.at(i,j*3+2); - green.at(i,j) = img.at(i,j*3+1); - blue.at(i,j) = img.at(i,j*3+0); - } + vector rgb_channel; + split(img,rgb_channel); for(int r=0 ;r <=order; r++) for(int g=0; g<=order;g++) @@ -391,18 +325,13 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, for(int i = 0;i(i,j)= - pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); + pow(rgb_channel[2].at(i,j),r)*pow(rgb_channel[1].at(i,j),g)* + pow(rgb_channel[0].at(i,j),b); vector curGrad; gradvector(curIm,curGrad); add_to_vector_poly(polyGrad,curGrad); } } - - red.release(); - green.release(); - blue.release(); - curIm.release(); } void Decolor::wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X) @@ -425,10 +354,6 @@ void Decolor::wei_update_matrix(vector < vector > &poly, vector > &comb, vector &wei) @@ -463,17 +388,8 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) int h=img.size().height; int w=img.size().width; - Mat red = Mat(img.size(),CV_32FC1); - Mat green = Mat(img.size(),CV_32FC1); - Mat blue = Mat(img.size(),CV_32FC1); - - for(int i=0;i(i,j) = img.at(i,j*3+2); - green.at(i,j) = img.at(i,j*3+1); - blue.at(i,j) = img.at(i,j*3+0); - } + vector rgb_channel; + split(img,rgb_channel); int kk =0; @@ -485,8 +401,8 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int i = 0;i(i,j)=Gray.at(i,j) + - (float) wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); + (float) wei[kk]*pow(rgb_channel[2].at(i,j),r)*pow(rgb_channel[1].at(i,j),g)* + pow(rgb_channel[0].at(i,j),b); kk=kk+1; } @@ -496,7 +412,7 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int i=0;i(i,j) < minval) minval = Gray.at(i,j); @@ -507,8 +423,4 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int i=0;i(i,j) = (Gray.at(i,j) - minval)/(maxval - minval); - - red.release(); - green.release(); - blue.release(); } From 35d9ca6483bfb5f7f87d3e502f105655a4f31a7b Mon Sep 17 00:00:00 2001 From: siddharth Date: Wed, 9 Oct 2013 21:49:57 +0530 Subject: [PATCH 36/97] Changes done in cloning module --- modules/photo/include/opencv2/photo.hpp | 4 +- modules/photo/src/contrast_preserve.cpp | 12 +- modules/photo/src/seamless_cloning.cpp | 43 +- modules/photo/src/seamless_cloning.hpp | 660 ++++++++---------------- 4 files changed, 221 insertions(+), 498 deletions(-) diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 1e83608800..256366afad 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -313,8 +313,8 @@ CV_EXPORTS_W Ptr createMergeRobertson(); float alpha = 0.2, float beta = 0.4); CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, - double low_threshold, double high_threshold, - int kernel_size); + double low_threshold = 30, double high_threshold = 45, + int kernel_size = 3); CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4); diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index c60e7184b9..7794b3646d 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -127,14 +127,14 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) temp1.push_back(val + Cg[i]); } - double ans = 0.0; - double ans1 = 0.0; + double pos = 0.0; + double neg = 0.0; for(unsigned int i =0;i EXPsum; diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp index b00a7bf379..c49f4a27bb 100644 --- a/modules/photo/src/seamless_cloning.cpp +++ b/modules/photo/src/seamless_cloning.cpp @@ -41,6 +41,7 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" +#include "opencv2/highgui.hpp" #include #include @@ -148,19 +149,7 @@ void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); - int channel = 3; - for(int i=0;i(i,j) == 255) - { - for(int c=0;c(i,j*channel+c) = src.at(i,j*channel+c); - } - } - - } + src.copyTo(cs_mask,gray); Cloning obj; obj.local_color_change(src,cs_mask,gray,blend,red,green,blue); @@ -186,19 +175,7 @@ void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); - int channel = 3; - for(int i=0;i(i,j) == 255) - { - for(int c=0;c(i,j*channel+c) = src.at(i,j*channel+c); - } - } - - } + src.copyTo(cs_mask,gray); Cloning obj; obj.illum_change(src,cs_mask,gray,blend,alpha,beta); @@ -223,19 +200,7 @@ void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst, Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); - int channel = 3; - for(int i=0;i(i,j) == 255) - { - for(int c=0;c(i,j*channel+c) = src.at(i,j*channel+c); - } - } - - } + src.copyTo(cs_mask,gray); Cloning obj; obj.texture_flatten(src,cs_mask,gray,low_threshold,high_threshold,kernel_size,blend); diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index b000e1a303..90bd2e4767 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -49,30 +49,32 @@ using namespace std; using namespace cv; -#define pi 3.1416 - class Cloning { public: - Mat grx,gry,sgx,sgy,r_channel,g_channel,b_channel,smask1,grx32,gry32; - Mat smask,srx32,sry32; - Mat rx_channel,ry_channel,gx_channel,gy_channel,bx_channel,by_channel,resultr,resultg,resultb; - void init(Mat &I, Mat &wmask); - void calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy); + vector rgb_channel, rgbx_channel, rgby_channel, output; + Mat grx, gry, sgx, sgy, srx32, sry32, grx32, gry32, smask, smask1; + void init_var(Mat &I, Mat &wmask); + void initialization(Mat &I, Mat &mask, Mat &wmask); + void scalar_product(Mat mat, float r, float g, float b); + void array_product(Mat mat1, Mat mat2, Mat mat3); + void poisson(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy); + void evaluate(Mat &I, Mat &wmask, Mat &cloned); void getGradientx(const Mat &img, Mat &gx); void getGradienty(const Mat &img, Mat &gy); void lapx(const Mat &img, Mat &gxx); void lapy(const Mat &img, Mat &gyy); - void dst(double *gtest, double *gfinal,int h,int w); - void idst(double *gtest, double *gfinal,int h,int w); + void dst(double *mod_diff, double *sineTransform,int h,int w); + void idst(double *mod_diff, double *sineTransform,int h,int w); void transpose(double *mat, double *mat_t,int h,int w); + void solve(const Mat &img, double *mod_diff, Mat &result); void poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result); - void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num); - void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red_mul, float green_mul, float blue_mul); - void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta); - void texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, double high_threhold, int kernel_size, Mat &final); + void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, int num); + void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float red_mul, float green_mul, float blue_mul); + void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alpha, float beta); + void texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, double high_threhold, int kernel_size, Mat &cloned); }; void Cloning::getGradientx( const Mat &img, Mat &gx) @@ -80,8 +82,6 @@ void Cloning::getGradientx( const Mat &img, Mat &gx) int w = img.size().width; int h = img.size().height; int channel = img.channels(); - - gx = Mat::zeros(img.size(),CV_32FC3); for(int i=0;i(i,j*channel+c) = (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); } + } void Cloning::getGradienty( const Mat &img, Mat &gy) @@ -96,8 +97,6 @@ void Cloning::getGradienty( const Mat &img, Mat &gy) int w = img.size().width; int h = img.size().height; int channel = img.channels(); - - gy = Mat::zeros(img.size(),CV_32FC3); for(int i=0;i(temp), Mat::zeros(temp.size(), CV_32F)}; - Mat complex1; + Mat result; int p=0; for(int i=0;i(r,0) = (float) gtest[idx]; + temp.at(r,0) = (float) mod_diff[idx]; } temp.at(h+1,0)=0.0; @@ -167,54 +163,49 @@ void Cloning::dst(double *gtest, double *gfinal,int h,int w) for(int j=h-1, r=h+2;j>=0;j--,r++) { idx = j*w+i; - temp.at(r,0) = (float) (-1.0 * gtest[idx]); + temp.at(r,0) = (float) (-1.0 * mod_diff[idx]); } - merge(planes, 2, complex1); + merge(planes, 2, result); - dft(complex1,complex1,0,0); + dft(result,result,0,0); - Mat planes1[] = {Mat::zeros(complex1.size(), CV_32F), Mat::zeros(complex1.size(), CV_32F)}; + Mat planes1[] = {Mat::zeros(result.size(), CV_32F), Mat::zeros(result.size(), CV_32F)}; - split(complex1, planes1); + split(result, planes1); std::complex two_i = std::sqrt(std::complex(-1)); - double fac = -2*imag(two_i); + double factor = -2*imag(two_i); for(int c=1,z=0;c(z,0) = (float) (planes1[1].at(c,0)/fac); + res.at(z,0) = (float) (planes1[1].at(c,0)/factor); } for(int q=0,z=0;q(z,0); + sineTransform[idx] = res.at(z,0); } p++; } - - temp.release(); - res.release(); - planes[0].release(); - planes[1].release(); - } -void Cloning::idst(double *gtest, double *gfinal,int h,int w) +void Cloning::idst(double *mod_diff, double *sineTransform,int h,int w) { int nn = h+1; unsigned long int idx; - dst(gtest,gfinal,h,w); + dst(mod_diff,sineTransform,h,w); for(int i= 0;i(i,j); } - - tmp.release(); - } -void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) +void Cloning::solve(const Mat &img, double *mod_diff, Mat &result) { - int w = img.size().width; int h = img.size().height; unsigned long int idx,idx1; - Mat lap = Mat(img.size(),CV_32FC1); - - for(int i =0;i(i,j)=gyy.at(i,j)+gxx.at(i,j); - - Mat bound = img.clone(); - - for(int i =1;i(i,j) = 0; - } - - double *f_bp = new double[h*w]; - - - for(int i =1;i(i,j) + (int)bound.at(i,(j+1)) + (int)bound.at(i,(j-1)) - + (int)bound.at(i-1,j) + (int)bound.at(i+1,j); - } - - Mat diff = Mat(h,w,CV_32FC1); - for(int i =0;i(i,j) = (float) (lap.at(i,j) - f_bp[idx]); - } - } - - lap.release(); - - double *gtest = new double[(h-2)*(w-2)]; - for(int i = 0 ; i < h-2;i++) - { - for(int j = 0 ; j < w-2; j++) - { - idx = i*(w-2) + j; - gtest[idx] = diff.at(i+1,j+1); - - } - } - - diff.release(); - ///////////////////////////////////////////////////// Find DST ///////////////////////////////////////////////////// - - double *gfinal = new double[(h-2)*(w-2)]; - double *gfinal_t = new double[(h-2)*(w-2)]; + double *sineTransform = new double[(h-2)*(w-2)]; + double *sineTransform_t = new double[(h-2)*(w-2)]; double *denom = new double[(h-2)*(w-2)]; - double *f3 = new double[(h-2)*(w-2)]; - double *f3_t = new double[(h-2)*(w-2)]; + double *invsineTransform = new double[(h-2)*(w-2)]; + double *invsineTransform_t = new double[(h-2)*(w-2)]; double *img_d = new double[(h)*(w)]; - dst(gtest,gfinal,h-2,w-2); + dst(mod_diff,sineTransform,h-2,w-2); - transpose(gfinal,gfinal_t,h-2,w-2); + transpose(sineTransform,sineTransform_t,h-2,w-2); - dst(gfinal_t,gfinal,w-2,h-2); + dst(sineTransform_t,sineTransform,w-2,h-2); - transpose(gfinal,gfinal_t,w-2,h-2); + transpose(sineTransform,sineTransform_t,w-2,h-2); - int cy=1; + int cy = 1; for(int i = 0 ; i < w-2;i++,cy++) { for(int j = 0,cx = 1; j < h-2; j++,cx++) { idx = j*(w-2) + i; - denom[idx] = (float) 2*cos(pi*cy/( (double) (w-1))) - 2 + 2*cos(pi*cx/((double) (h-1))) - 2; + denom[idx] = (float) 2*cos(CV_PI*cy/( (double) (w-1))) - 2 + 2*cos(CV_PI*cx/((double) (h-1))) - 2; } } for(idx = 0 ; idx < (unsigned)(w-2)*(h-2) ;idx++) { - gfinal_t[idx] = gfinal_t[idx]/denom[idx]; + sineTransform_t[idx] = sineTransform_t[idx]/denom[idx]; } - idst(gfinal_t,f3,h-2,w-2); + idst(sineTransform_t,invsineTransform,h-2,w-2); - transpose(f3,f3_t,h-2,w-2); + transpose(invsineTransform,invsineTransform_t,h-2,w-2); - idst(f3_t,f3,w-2,h-2); + idst(invsineTransform_t,invsineTransform,w-2,h-2); - transpose(f3,f3_t,w-2,h-2); + transpose(invsineTransform,invsineTransform_t,w-2,h-2); for(int i = 0 ; i < h;i++) { @@ -363,7 +299,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) { idx = i*w + j; idx1= id1*(w-2) + id2; - img_d[idx] = f3_t[idx1]; + img_d[idx] = invsineTransform_t[idx1]; } } @@ -381,35 +317,76 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) } } - delete [] gfinal; - delete [] gfinal_t; + delete [] sineTransform; + delete [] sineTransform_t; delete [] denom; - delete [] f3; - delete [] f3_t; + delete [] invsineTransform; + delete [] invsineTransform_t; delete [] img_d; - delete [] gtest; - delete [] f_bp; } -void Cloning::init(Mat &I, Mat &wmask) +void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) { + int w = img.size().width; + int h = img.size().height; + + unsigned long int idx; + + Mat lap = Mat(img.size(),CV_32FC1); + + lap = gxx + gyy; + + Mat bound = img.clone(); + + rectangle(bound, Point(1, 1), Point(img.cols-2, img.rows-2), Scalar::all(0), -1); + + double *boundary_point = new double[h*w]; + + for(int i =1;i(i,j) + (int)bound.at(i,(j+1)) + (int)bound.at(i,(j-1)) + + (int)bound.at(i-1,j) + (int)bound.at(i+1,j); + } + + Mat diff = Mat(h,w,CV_32FC1); + for(int i =0;i(i,j) = (float) (lap.at(i,j) - boundary_point[idx]); + } + } + + double *mod_diff = new double[(h-2)*(w-2)]; + for(int i = 0 ; i < h-2;i++) + { + for(int j = 0 ; j < w-2; j++) + { + idx = i*(w-2) + j; + mod_diff[idx] = diff.at(i+1,j+1); + + } + } + ///////////////////////////////////////////////////// Find DST ///////////////////////////////////////////////////// + + solve(img,mod_diff,result); + + delete [] mod_diff; + delete [] boundary_point; +} + +void Cloning::init_var(Mat &I, Mat &wmask) +{ grx = Mat(I.size(),CV_32FC3); gry = Mat(I.size(),CV_32FC3); sgx = Mat(I.size(),CV_32FC3); sgy = Mat(I.size(),CV_32FC3); - r_channel = Mat::zeros(I.size(),CV_8UC1); - g_channel = Mat::zeros(I.size(),CV_8UC1); - b_channel = Mat::zeros(I.size(),CV_8UC1); - - for(int i=0;i(i,j) = I.at(i,j*3+0); - g_channel.at(i,j) = I.at(i,j*3+1); - b_channel.at(i,j) = I.at(i,j*3+2); - } + split(I,rgb_channel); smask = Mat(wmask.size(),CV_32FC1); srx32 = Mat(I.size(),CV_32FC3); @@ -419,22 +396,55 @@ void Cloning::init(Mat &I, Mat &wmask) gry32 = Mat(I.size(),CV_32FC3); } -void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) +void Cloning::initialization(Mat &I, Mat &mask, Mat &wmask) { + init_var(I,wmask); - int channel = I.channels(); + getGradientx(I,grx); + getGradienty(I,gry); + + getGradientx(mask,sgx); + getGradienty(mask,sgy); + + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); + + erode(wmask, wmask, Kernel, Point(-1,-1), 3); + + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); +} + +void Cloning::scalar_product(Mat mat, float r, float g, float b) +{ + vector channels; + split(mat,channels); + multiply(channels[2],r,channels[2]); + multiply(channels[1],g,channels[1]); + multiply(channels[0],b,channels[0]); + merge(channels,mat); +} + +void Cloning::array_product(Mat mat1, Mat mat2, Mat mat3) +{ + vector channels_temp1; + vector channels_temp2; + split(mat1,channels_temp1); + split(mat2,channels_temp2); + multiply(channels_temp2[2],mat3,channels_temp1[2]); + multiply(channels_temp2[1],mat3,channels_temp1[1]); + multiply(channels_temp2[0],mat3,channels_temp1[0]); + merge(channels_temp1,mat1); +} + +void Cloning::poisson(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) +{ Mat fx = Mat(I.size(),CV_32FC3); Mat fy = Mat(I.size(),CV_32FC3); - for(int i=0;i < I.size().height; i++) - for(int j=0; j < I.size().width; j++) - for(int c=0;c(i,j*channel+c) = - (gx.at(i,j*channel+c)+sx.at(i,j*channel+c)); - fy.at(i,j*channel+c) = - (gy.at(i,j*channel+c)+sy.at(i,j*channel+c)); - } + fx = gx + sx; + fy = gy + sy; Mat gxx = Mat(I.size(),CV_32FC3); Mat gyy = Mat(I.size(),CV_32FC3); @@ -442,79 +452,44 @@ void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) lapx(fx,gxx); lapy(fy,gyy); - rx_channel = Mat(I.size(),CV_32FC1); - gx_channel = Mat(I.size(),CV_32FC1); - bx_channel = Mat(I.size(),CV_32FC1); + split(gxx,rgbx_channel); + split(gyy,rgby_channel); - for(int i=0;i(i,j) = gxx.at(i,j*3+0); - gx_channel.at(i,j) = gxx.at(i,j*3+1); - bx_channel.at(i,j) = gxx.at(i,j*3+2); - } - - ry_channel = Mat(I.size(),CV_32FC1); - gy_channel = Mat(I.size(),CV_32FC1); - by_channel = Mat(I.size(),CV_32FC1); - - for(int i=0;i(i,j) = gyy.at(i,j*3+0); - gy_channel.at(i,j) = gyy.at(i,j*3+1); - by_channel.at(i,j) = gyy.at(i,j*3+2); - } - - resultr = Mat(I.size(),CV_8UC1); - resultg = Mat(I.size(),CV_8UC1); - resultb = Mat(I.size(),CV_8UC1); - - poisson_solver(r_channel,rx_channel, ry_channel,resultr); - poisson_solver(g_channel,gx_channel, gy_channel,resultg); - poisson_solver(b_channel,bx_channel, by_channel,resultb); + split(I,output); + poisson_solver(rgb_channel[2],rgbx_channel[2], rgby_channel[2],output[2]); + poisson_solver(rgb_channel[1],rgbx_channel[1], rgby_channel[1],output[1]); + poisson_solver(rgb_channel[0],rgbx_channel[0], rgby_channel[0],output[0]); } -void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num) +void Cloning::evaluate(Mat &I, Mat &wmask, Mat &cloned) { - init(I,wmask); + bitwise_not(wmask,wmask); + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); + + array_product(grx32,grx,smask1); + array_product(gry32,gry,smask1); + + poisson(I,grx32,gry32,srx32,sry32); + + merge(output,cloned); +} + +void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, int num) +{ int w = I.size().width; int h = I.size().height; int channel = I.channels(); - getGradientx(I,grx); - getGradienty(I,gry); - - if(num != 3) - { - getGradientx(mask,sgx); - getGradienty(mask,sgy); - } - - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); + initialization(I,mask,wmask); if(num == 1) { - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } + array_product(srx32,sgx,smask); + array_product(sry32,sgy,smask); } else if(num == 2) @@ -546,194 +521,53 @@ void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num) Mat gray = Mat(mask.size(),CV_8UC1); Mat gray8 = Mat(mask.size(),CV_8UC3); cvtColor(mask, gray, COLOR_BGR2GRAY ); + vector temp; + split(I,temp); + gray.copyTo(temp[2]); + gray.copyTo(temp[1]); + gray.copyTo(temp[0]); - for(int i=0;i(i,j*3+0) = gray.at(i,j); - gray8.at(i,j*3+1) = gray.at(i,j); - gray8.at(i,j*3+2) = gray.at(i,j); - } - + merge(temp,gray8); getGradientx(gray8,sgx); getGradienty(gray8,sgy); - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } + array_product(srx32,sgx,smask); + array_product(sry32,sgy,smask); } - bitwise_not(wmask,wmask); - - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } - - calc(I,grx32,gry32,srx32,sry32); - - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } - + evaluate(I,wmask,cloned); } -void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red_mul=1.0, +void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float red_mul=1.0, float green_mul=1.0, float blue_mul=1.0) { - init(I,wmask); + initialization(I,mask,wmask); - int w = I.size().width; - int h = I.size().height; - int channel = I.channels(); - - getGradientx(I,grx); - getGradienty(I,gry); - - getGradientx(mask,sgx); - getGradienty(mask,sgy); - - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } - - Mat factor = Mat(I.size(),CV_32FC3); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - { - factor.at(i,j*channel+0) = blue_mul; - factor.at(i,j*channel+1) = green_mul; - factor.at(i,j*channel+2) = red_mul; - } - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - srx32.at(i,j*channel+c)*factor.at(i,j*channel+c); - sry32.at(i,j*channel+c) = - sry32.at(i,j*channel+c)*factor.at(i,j*channel+c); - } - - bitwise_not(wmask,wmask); - - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } - - calc(I,grx32,gry32,srx32,sry32); - - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + array_product(srx32,sgx,smask); + array_product(sry32,sgy,smask); + scalar_product(srx32,red_mul,green_mul,blue_mul); + scalar_product(sry32,red_mul,green_mul,blue_mul); + evaluate(I,wmask,cloned); } -void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta) +void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alpha, float beta) { - init(I,wmask); - - int w = I.size().width; - int h = I.size().height; int channel = I.channels(); - getGradientx(I,grx); - getGradienty(I,gry); - - getGradientx(mask,sgx); - getGradienty(mask,sgy); - - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } + initialization(I,mask,wmask); + array_product(srx32,sgx,smask); + array_product(sry32,sgy,smask); Mat mag = Mat(I.size(),CV_32FC3); - I.convertTo(mag,CV_32FC3,1.0/255.0); + magnitude(srx32,sry32,mag); - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - sqrt(pow(srx32.at(i,j*channel+c),2) + pow(sry32.at(i,j*channel+c),2)); - } - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) != 0) { @@ -744,108 +578,32 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alph } } - bitwise_not(wmask,wmask); - - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } - - calc(I,grx32,gry32,srx32,sry32); - - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + evaluate(I,wmask,cloned); } - void Cloning::texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, - double high_threshold, int kernel_size, Mat &final) + double high_threshold, int kernel_size, Mat &cloned) { - init(I,wmask); + int channel = mask.channels(); - int w = I.size().width; - int h = I.size().height; - - getGradientx(I,grx); - getGradienty(I,gry); - - getGradientx(mask,sgx); - getGradienty(mask,sgy); - - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); + initialization(I,mask,wmask); Mat out = Mat(mask.size(),CV_8UC1); Canny(mask,out,low_threshold,high_threshold,kernel_size); - int channel = mask.channels(); - for(int i=0;i(i,j) != 255) - { + { sgx.at(i,j*channel+c) = 0.0; sgy.at(i,j*channel+c) = 0.0; - } + } } - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } + array_product(srx32,sgx,smask); + array_product(sry32,sgy,smask); - bitwise_not(wmask,wmask); - - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } - - calc(I,grx32,gry32,srx32,sry32); - - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + evaluate(I,wmask,cloned); } From 2f65a0d4bab9c38854042a7e64814c59240f2f29 Mon Sep 17 00:00:00 2001 From: siddharth Date: Thu, 17 Oct 2013 21:14:31 +0530 Subject: [PATCH 37/97] Changes done in npr module --- modules/photo/src/npr.cpp | 99 +++------------ modules/photo/src/npr.hpp | 162 ++++++++----------------- modules/photo/src/seamless_cloning.cpp | 30 ++--- modules/photo/src/seamless_cloning.hpp | 45 +++---- 4 files changed, 95 insertions(+), 241 deletions(-) diff --git a/modules/photo/src/npr.cpp b/modules/photo/src/npr.cpp index 08c7753410..a3b38d4ee1 100644 --- a/modules/photo/src/npr.cpp +++ b/modules/photo/src/npr.cpp @@ -79,34 +79,24 @@ void cv::detailEnhance(InputArray _src, OutputArray _dst, float sigma_s, float s int h = I.size().height; int w = I.size().width; - int channel = I.channels(); float factor = 3.0; Mat img = Mat(I.size(),CV_32FC3); I.convertTo(img,CV_32FC3,1.0/255.0); - Mat res = Mat(h,w,CV_32FC3); + Mat res = Mat(h,w,CV_32FC1); dst.convertTo(res,CV_32FC3,1.0/255.0); Mat result = Mat(img.size(),CV_32FC3); Mat lab = Mat(img.size(),CV_32FC3); - Mat l_channel = Mat(img.size(),CV_32FC1); - Mat a_channel = Mat(img.size(),CV_32FC1); - Mat b_channel = Mat(img.size(),CV_32FC1); + vector lab_channel; cvtColor(img,lab,COLOR_BGR2Lab); - - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - { - l_channel.at(i,j) = lab.at(i,j*channel+0); - a_channel.at(i,j) = lab.at(i,j*channel+1); - b_channel.at(i,j) = lab.at(i,j*channel+2); - } + split(lab,lab_channel); Mat L = Mat(img.size(),CV_32FC1); - l_channel.convertTo(L,CV_32FC1,1.0/255.0); + lab_channel[0].convertTo(L,CV_32FC1,1.0/255.0); Domain_Filter obj; @@ -114,23 +104,13 @@ void cv::detailEnhance(InputArray _src, OutputArray _dst, float sigma_s, float s Mat detail = Mat(h,w,CV_32FC1); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - detail.at(i,j) = L.at(i,j) - res.at(i,j); + detail = L - res; + multiply(detail,factor,detail); + L = res + detail; - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - L.at(i,j) = res.at(i,j) + factor*detail.at(i,j); + L.convertTo(lab_channel[0],CV_32FC1,255); - L.convertTo(l_channel,CV_32FC1,255); - - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - { - lab.at(i,j*channel+0) = l_channel.at(i,j); - lab.at(i,j*channel+1) = a_channel.at(i,j); - lab.at(i,j*channel+2) = b_channel.at(i,j); - } + merge(lab_channel,lab); cvtColor(lab,result,COLOR_Lab2BGR); result.convertTo(dst,CV_8UC3,255); @@ -174,64 +154,21 @@ void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sig int channel = img.channels(); Mat res = Mat(h,w,CV_32FC3); + Mat magnitude = Mat(h,w,CV_32FC1); Domain_Filter obj; obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); - vector planes; - split(res, planes); - - Mat magXR = Mat(h, w, CV_32FC1); - Mat magYR = Mat(h, w, CV_32FC1); - - Mat magXG = Mat(h, w, CV_32FC1); - Mat magYG = Mat(h, w, CV_32FC1); - - Mat magXB = Mat(h, w, CV_32FC1); - Mat magYB = Mat(h, w, CV_32FC1); - - Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); - Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); - - Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); - Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); - - Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); - Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); - - Mat magx = Mat(h,w,CV_32FC1); - Mat magy = Mat(h,w,CV_32FC1); - - Mat mag1 = Mat(h,w,CV_32FC1); - Mat mag2 = Mat(h,w,CV_32FC1); - Mat mag3 = Mat(h,w,CV_32FC1); - - magnitude(magXR,magYR,mag1); - magnitude(magXG,magYG,mag2); - magnitude(magXB,magYB,mag3); - - Mat magnitude = Mat(h,w,CV_32FC1); - - for(int i =0;i < h;i++) - for(int j=0;j(i,j) = mag1.at(i,j) + mag2.at(i,j) + mag3.at(i,j); - } - - for(int i =0;i < h;i++) - for(int j=0;j(i,j) = 1.0f - magnitude.at(i,j); - } + obj.find_magnitude(res,magnitude,2); Mat stylized = Mat(h,w,CV_32FC3); - for(int i =0;i < h;i++) - for(int j=0;j(i,j*channel + c) = res.at(i,j*channel + c) * magnitude.at(i,j); - } + vector temp; + split(res,temp); + multiply(temp[0],magnitude,temp[0]); + multiply(temp[1],magnitude,temp[1]); + multiply(temp[2],magnitude,temp[2]); + merge(temp,stylized); stylized.convertTo(dst,CV_8UC3,255); } @@ -259,7 +196,7 @@ void cv::edgeEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sig obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); - obj.find_magnitude(res,magnitude); + obj.find_magnitude(res,magnitude,1); magnitude.convertTo(dst,CV_8UC1,255); } diff --git a/modules/photo/src/npr.hpp b/modules/photo/src/npr.hpp index 3f5519d1bb..733d418d58 100644 --- a/modules/photo/src/npr.hpp +++ b/modules/photo/src/npr.hpp @@ -61,7 +61,7 @@ class Domain_Filter void getGradienty( const Mat &img, Mat &gy); void diffx(const Mat &img, Mat &temp); void diffy(const Mat &img, Mat &temp); - void find_magnitude(Mat &img, Mat &mag); + void find_magnitude(Mat &img, Mat &mag, int flags); void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius); void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h); void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius); @@ -131,9 +131,8 @@ void Domain_Filter::getGradienty( const Mat &img, Mat &gy) } } -void Domain_Filter::find_magnitude(Mat &img, Mat &mag) +void Domain_Filter::find_magnitude(Mat &img, Mat &mag, int flags) { - int h = img.rows; int w = img.cols; @@ -149,17 +148,28 @@ void Domain_Filter::find_magnitude(Mat &img, Mat &mag) Mat magXB = Mat(h, w, CV_32FC1); Mat magYB = Mat(h, w, CV_32FC1); - getGradientx(planes[0], magXR); - getGradienty(planes[0], magYR); + if(flags == 1) + { + getGradientx(planes[0], magXR); + getGradienty(planes[0], magYR); - getGradientx(planes[1], magXG); - getGradienty(planes[1], magYG); + getGradientx(planes[1], magXG); + getGradienty(planes[1], magYG); - getGradientx(planes[2], magXR); - getGradienty(planes[2], magYR); + getGradientx(planes[2], magXR); + getGradienty(planes[2], magYR); + } + else if(flags == 2) + { + Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); + Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); - Mat magx = Mat(h,w,CV_32FC1); - Mat magy = Mat(h,w,CV_32FC1); + Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); + Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); + + Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); + Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); + } Mat mag1 = Mat(h,w,CV_32FC1); Mat mag2 = Mat(h,w,CV_32FC1); @@ -169,39 +179,21 @@ void Domain_Filter::find_magnitude(Mat &img, Mat &mag) magnitude(magXG,magYG,mag2); magnitude(magXB,magYB,mag3); - for(int i =0;i < h;i++) - for(int j=0;j(i,j) = mag1.at(i,j) + mag2.at(i,j) + mag3.at(i,j); - } - - - for(int i =0;i < h;i++) - for(int j=0;j(i,j) = 1.0f - mag.at(i,j); - } - + mag = mag1 + mag2 + mag3; + mag = 1.0f - mag; } void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) { - - float a; - int h = output.rows; int w = output.cols; int channel = output.channels(); - a = (float) exp((-1.0 * sqrt(2.0)) / sigma_h); + float a = (float) exp((-1.0 * sqrt(2.0)) / sigma_h); Mat temp = Mat(h,w,CV_32FC3); - for(int i =0; i < h;i++) - for(int j=0;j(i,j*channel+c) = output.at(i,j*channel+c); - + output.copyTo(temp); Mat V = Mat(h,w,CV_32FC1); for(int i=0;i(i,j*channel+c) = temp.at(i,j*channel+c); - - temp.release(); - V.release(); + temp.copyTo(output); } void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius) @@ -249,12 +234,8 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float Mat lower_pos = Mat(h,w,CV_32FC1); Mat upper_pos = Mat(h,w,CV_32FC1); - for(int i=0;i(i,j) = hz.at(i,j) - radius; - upper_pos.at(i,j) = hz.at(i,j) + radius; - } + lower_pos = hz - radius; + upper_pos = hz + radius; lower_idx = Mat::zeros(h,w,CV_32FC1); upper_idx = Mat::zeros(h,w,CV_32FC1); @@ -334,19 +315,11 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float upper_idx.at(i,j) = temp_upper_idx.at(0,j) + 1; } - lower_pos_row.release(); - upper_pos_row.release(); - temp_lower_idx.release(); - temp_upper_idx.release(); } - for(int i=0;i(i,j) = upper_idx.at(i,j) - lower_idx.at(i,j); - + psketch = upper_idx - lower_idx; } void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float radius) { - int h = output.rows; int w = output.cols; int channel = output.channels(); @@ -377,24 +350,25 @@ void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float r Mat a = Mat::zeros(h,w,CV_32FC1); Mat b = Mat::zeros(h,w,CV_32FC1); + // Compute the box filter using a summed area table. for(int c=0;c(i,j) = (c+1)*flag.at(i,j); + multiply(flag,c+1,flag); - for(int i=0;i(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (lower_idx.at(i,j) - 1) * h + indices.at(i,j); - b.at(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (upper_idx.at(i,j) - 1) * h + indices.at(i,j); + Mat temp1, temp2; + multiply(flag - 1,h*(w+1),temp1); + multiply(lower_idx - 1,h,temp2); + a = temp1 + temp2 + indices; - } + multiply(flag - 1,h*(w+1),temp1); + multiply(upper_idx - 1,h,temp2); + b = temp1 + temp2 + indices; int p,q,r,rem; int p1,q1,r1,rem1; + // Calculating indices for(int i=0;i(i,j)/(h*(w+1)); rem1 = (int) a.at(i,j) - r1*h*(w+1); q1 = rem1/h; @@ -427,18 +400,13 @@ void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float r q1=q1-1; } - final.at(i,j*channel+2-c) = (box_filter.at(p-1,q*channel+(2-r)) - box_filter.at(p1-1,q1*channel+(2-r1))) /(upper_idx.at(i,j) - lower_idx.at(i,j)); } } } - for(int i=0;i(i,j*channel+c) = final.at(i,j*channel+c); - + final.copyTo(output); } void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r) { @@ -482,20 +450,15 @@ void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r Mat final = Mat(h,w,CV_32FC3); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - { - horiz.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * distx.at(i,j); - vert.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * disty.at(i,j); - } + Mat tempx,tempy; + multiply(distx,sigma_s/sigma_r,tempx); + multiply(disty,sigma_s/sigma_r,tempy); + horiz = 1.0f + tempx; + vert = 1.0f + tempy; O = Mat(h,w,CV_32FC3); - - for(int i =0;i(i,j*channel+c) = img.at(i,j*channel+c); + img.copyTo(O); O_t = Mat(w,h,CV_32FC3); @@ -588,17 +551,14 @@ void Domain_Filter::pencil_sketch(const Mat &img, Mat &sketch, Mat &color_res, f init(img,2,sigma_s,sigma_r); int h = img.size().height; int w = img.size().width; - int channel = img.channels(); /////////////////////// convert to YCBCR model for color pencil drawing ////////////////////////////////////////////////////// Mat color_sketch = Mat(h,w,CV_32FC3); - Mat Y_channel = Mat(h,w,CV_32FC1); - Mat U_channel = Mat(h,w,CV_32FC1); - Mat V_channel = Mat(h,w,CV_32FC1); cvtColor(img,color_sketch,COLOR_BGR2YCrCb); + vector YUV_channel; Mat vert_t = ct_V.t(); float sigma_h = sigma_s; @@ -635,33 +595,11 @@ void Domain_Filter::pencil_sketch(const Mat &img, Mat &sketch, Mat &color_res, f if(i==0) { sketch = pen_res.clone(); - - for(int k = 0; k < h; k++) - for(int j = 0; j < w; j++) - { - Y_channel.at(k,j) = color_sketch.at(k,j*channel+0); - U_channel.at(k,j) = color_sketch.at(k,j*channel+1); - V_channel.at(k,j) = color_sketch.at(k,j*channel+2); - } - - - for(int k=0;k(k,j) = pen_res.at(k,j); - - // cvMerge(Y_channel,U_channel,V_channel,0,color_sketch); - for(int k = 0; k < h; k++) - for(int j = 0; j < w; j++) - { - color_sketch.at(k,j*channel+0) = Y_channel.at(k,j); - color_sketch.at(k,j*channel+1) = U_channel.at(k,j); - color_sketch.at(k,j*channel+2) = V_channel.at(k,j); - } - + split(color_sketch,YUV_channel); + pen_res.copyTo(YUV_channel[0]); + merge(YUV_channel,color_sketch); cvtColor(color_sketch,color_res,COLOR_YCrCb2BGR); - } } - } diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp index c49f4a27bb..63f4530477 100644 --- a/modules/photo/src/seamless_cloning.cpp +++ b/modules/photo/src/seamless_cloning.cpp @@ -41,7 +41,6 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" -#include "opencv2/highgui.hpp" #include #include @@ -100,30 +99,17 @@ void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point exit(0); } - for(int i=minx, k=minxd;i<(minx+lenx);i++,k++) - for(int j=miny,l=minyd ;j<(miny+leny);j++,l++) - { - dst_mask.at(k,l) = gray.at(i,j); - } + Rect roi_d(minyd,minxd,leny,lenx); + Rect roi_s(miny,minx,leny,lenx); - int channel = 3; + Mat destinationROI = dst_mask(roi_d); + Mat sourceROI = cs_mask(roi_s); - for(int i=minx;i<(minx+lenx);i++) - for(int j=miny;j<(miny+leny);j++) - { - for(int c=0;c<3;c++) - { - if(gray.at(i,j) == 255) - cs_mask.at(i,j*channel+c) = src.at(i,j*channel+c); - } - } + gray(roi_s).copyTo(destinationROI); + src(roi_s).copyTo(sourceROI,gray(roi_s)); - for(int i=minx, k=minxd;i<(minx+lenx);i++,k++) - for(int j=miny,l=minyd ;j<(miny+leny);j++,l++) - { - for(int c=0;c(k,l*channel+c) = cs_mask.at(i,j*channel+c); - } + destinationROI = cd_mask(roi_d); + cs_mask(roi_s).copyTo(destinationROI); Cloning obj; obj.normal_clone(dest,cd_mask,dst_mask,blend,flags); diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index 90bd2e4767..612d764d95 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -555,8 +555,6 @@ void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, flo void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alpha, float beta) { - int channel = I.channels(); - initialization(I,mask,wmask); array_product(srx32,sgx,smask); @@ -565,18 +563,20 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alp Mat mag = Mat(I.size(),CV_32FC3); magnitude(srx32,sry32,mag); - for(int i=0;i < I.size().height; i++) - for(int j=0; j < I.size().width; j++) - for(int c=0;c < channel;++c) - { - if(srx32.at(i,j*channel+c) != 0) - { - srx32.at(i,j*channel+c) = - pow(alpha,beta)*srx32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); - sry32.at(i,j*channel+c) = - pow(alpha,beta)*sry32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); - } - } + Mat multX, multY, multx_temp, multy_temp; + + multiply(srx32,pow(alpha,beta),multX); + pow(mag,-1*beta, multx_temp); + multiply(multX,multx_temp,srx32); + + multiply(sry32,pow(alpha,beta),multY); + pow(mag,-1*beta, multy_temp); + multiply(multY,multy_temp,sry32); + + Mat zeroMask = (srx32 != 0); + + srx32.copyTo(srx32, zeroMask); + sry32.copyTo(sry32, zeroMask); evaluate(I,wmask,cloned); } @@ -584,23 +584,16 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alp void Cloning::texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, double high_threshold, int kernel_size, Mat &cloned) { - int channel = mask.channels(); - initialization(I,mask,wmask); Mat out = Mat(mask.size(),CV_8UC1); Canny(mask,out,low_threshold,high_threshold,kernel_size); - for(int i=0;i(i,j) != 255) - { - sgx.at(i,j*channel+c) = 0.0; - sgy.at(i,j*channel+c) = 0.0; - } - } + Mat zeros(sgx.size(), CV_32FC3); + zeros.setTo(0); + Mat zerosMask = (out != 255); + zeros.copyTo(sgx, zerosMask); + zeros.copyTo(sgy, zerosMask); array_product(srx32,sgx,smask); array_product(sry32,sgy,smask); From 33e6c074855c8d84e28fff8e3158a33bf17be800 Mon Sep 17 00:00:00 2001 From: siddharth Date: Mon, 21 Oct 2013 19:54:32 +0530 Subject: [PATCH 38/97] Removed build errors and removed test images Removed conflict Error fix 1 Error fix 2 Error fix 3 Error fix 3 Error fix 4 Error fix 5 Error fix 6 Error fix 7 Error fix 8 Error fix 9 Error fix 10 Error fix 11 Error fix 12 Errors fixed Removed opencv_extra folder inside opencv folder --- modules/photo/doc/cloning.rst | 2 +- modules/photo/doc/npr.rst | 15 -- modules/photo/include/opencv2/photo.hpp | 303 ++++++++++++------------ modules/photo/src/contrast_preserve.hpp | 11 +- modules/photo/src/npr.cpp | 31 +-- modules/photo/src/npr.hpp | 30 +-- modules/photo/test/test_npr.cpp | 16 -- samples/cpp/cloning_demo.cpp | 2 +- samples/cpp/npr_demo.cpp | 10 +- 9 files changed, 171 insertions(+), 249 deletions(-) mode change 100644 => 100755 modules/photo/test/test_npr.cpp diff --git a/modules/photo/doc/cloning.rst b/modules/photo/doc/cloning.rst index 3a115e8390..48c5b24ba1 100644 --- a/modules/photo/doc/cloning.rst +++ b/modules/photo/doc/cloning.rst @@ -80,7 +80,7 @@ textureFlattening By retaining only the gradients at edge locations, before integrating with the Poisson solver, one washes out the texture of the selected region, giving its contents a flat aspect. Here Canny Edge Detector is used. -.. ocv:function:: void textureFlattening(InputArray src, InputArray mask, OutputArray dst, double low_threshold, double high_threshold, int kernel_size) +.. ocv:function:: void textureFlattening(InputArray src, InputArray mask, OutputArray dst, double low_threshold=30 , double high_threshold=45, int kernel_size=3) :param src: Input 8-bit 3-channel image. diff --git a/modules/photo/doc/npr.rst b/modules/photo/doc/npr.rst index e547689876..48e2db2a7d 100644 --- a/modules/photo/doc/npr.rst +++ b/modules/photo/doc/npr.rst @@ -72,18 +72,3 @@ Stylization aims to produce digital imagery with a wide variety of effects not f :param sigma_s: Range between 0 to 200. :param sigma_r: Range between 0 to 1. - - -edgeEnhance ------------ -Able to suppress low-amplitude details and enhance edges. - -.. ocv:function:: void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45) - - :param src: Input 8-bit 3-channel image. - - :param dst: Output 8-bit 1-channel image. - - :param sigma_s: Range between 0 to 200. - - :param sigma_r: Range between 0 to 1. diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 256366afad..949c1cfb62 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -93,213 +93,213 @@ namespace cv float h = 3, float hColor = 3, int templateWindowSize = 7, int searchWindowSize = 21); -enum { LDR_SIZE = 256 }; + enum { LDR_SIZE = 256 }; -class CV_EXPORTS_W Tonemap : public Algorithm -{ -public: - CV_WRAP virtual void process(InputArray src, OutputArray dst) = 0; + class CV_EXPORTS_W Tonemap : public Algorithm + { + public: + CV_WRAP virtual void process(InputArray src, OutputArray dst) = 0; - CV_WRAP virtual float getGamma() const = 0; - CV_WRAP virtual void setGamma(float gamma) = 0; -}; + CV_WRAP virtual float getGamma() const = 0; + CV_WRAP virtual void setGamma(float gamma) = 0; + }; -CV_EXPORTS_W Ptr createTonemap(float gamma = 1.0f); + CV_EXPORTS_W Ptr createTonemap(float gamma = 1.0f); -// "Adaptive Logarithmic Mapping For Displaying HighContrast Scenes", Drago et al., 2003 + // "Adaptive Logarithmic Mapping For Displaying HighContrast Scenes", Drago et al., 2003 -class CV_EXPORTS_W TonemapDrago : public Tonemap -{ -public: + class CV_EXPORTS_W TonemapDrago : public Tonemap + { + public: - CV_WRAP virtual float getSaturation() const = 0; - CV_WRAP virtual void setSaturation(float saturation) = 0; + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; - CV_WRAP virtual float getBias() const = 0; - CV_WRAP virtual void setBias(float bias) = 0; -}; + CV_WRAP virtual float getBias() const = 0; + CV_WRAP virtual void setBias(float bias) = 0; + }; -CV_EXPORTS_W Ptr createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f); + CV_EXPORTS_W Ptr createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f); -// "Fast Bilateral Filtering for the Display of High-Dynamic-Range Images", Durand, Dorsey, 2002 + // "Fast Bilateral Filtering for the Display of High-Dynamic-Range Images", Durand, Dorsey, 2002 -class CV_EXPORTS_W TonemapDurand : public Tonemap -{ -public: + class CV_EXPORTS_W TonemapDurand : public Tonemap + { + public: - CV_WRAP virtual float getSaturation() const = 0; - CV_WRAP virtual void setSaturation(float saturation) = 0; + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; - CV_WRAP virtual float getContrast() const = 0; - CV_WRAP virtual void setContrast(float contrast) = 0; + CV_WRAP virtual float getContrast() const = 0; + CV_WRAP virtual void setContrast(float contrast) = 0; - CV_WRAP virtual float getSigmaSpace() const = 0; - CV_WRAP virtual void setSigmaSpace(float sigma_space) = 0; + CV_WRAP virtual float getSigmaSpace() const = 0; + CV_WRAP virtual void setSigmaSpace(float sigma_space) = 0; - CV_WRAP virtual float getSigmaColor() const = 0; - CV_WRAP virtual void setSigmaColor(float sigma_color) = 0; -}; + CV_WRAP virtual float getSigmaColor() const = 0; + CV_WRAP virtual void setSigmaColor(float sigma_color) = 0; + }; -CV_EXPORTS_W Ptr -createTonemapDurand(float gamma = 1.0f, float contrast = 4.0f, float saturation = 1.0f, float sigma_space = 2.0f, float sigma_color = 2.0f); + CV_EXPORTS_W Ptr + createTonemapDurand(float gamma = 1.0f, float contrast = 4.0f, float saturation = 1.0f, float sigma_space = 2.0f, float sigma_color = 2.0f); -// "Dynamic Range Reduction Inspired by Photoreceptor Physiology", Reinhard, Devlin, 2005 + // "Dynamic Range Reduction Inspired by Photoreceptor Physiology", Reinhard, Devlin, 2005 -class CV_EXPORTS_W TonemapReinhard : public Tonemap -{ -public: - CV_WRAP virtual float getIntensity() const = 0; - CV_WRAP virtual void setIntensity(float intensity) = 0; + class CV_EXPORTS_W TonemapReinhard : public Tonemap + { + public: + CV_WRAP virtual float getIntensity() const = 0; + CV_WRAP virtual void setIntensity(float intensity) = 0; - CV_WRAP virtual float getLightAdaptation() const = 0; - CV_WRAP virtual void setLightAdaptation(float light_adapt) = 0; + CV_WRAP virtual float getLightAdaptation() const = 0; + CV_WRAP virtual void setLightAdaptation(float light_adapt) = 0; - CV_WRAP virtual float getColorAdaptation() const = 0; - CV_WRAP virtual void setColorAdaptation(float color_adapt) = 0; -}; + CV_WRAP virtual float getColorAdaptation() const = 0; + CV_WRAP virtual void setColorAdaptation(float color_adapt) = 0; + }; -CV_EXPORTS_W Ptr -createTonemapReinhard(float gamma = 1.0f, float intensity = 0.0f, float light_adapt = 1.0f, float color_adapt = 0.0f); + CV_EXPORTS_W Ptr + createTonemapReinhard(float gamma = 1.0f, float intensity = 0.0f, float light_adapt = 1.0f, float color_adapt = 0.0f); -// "Perceptual Framework for Contrast Processing of High Dynamic Range Images", Mantiuk et al., 2006 + // "Perceptual Framework for Contrast Processing of High Dynamic Range Images", Mantiuk et al., 2006 -class CV_EXPORTS_W TonemapMantiuk : public Tonemap -{ -public: - CV_WRAP virtual float getScale() const = 0; - CV_WRAP virtual void setScale(float scale) = 0; + class CV_EXPORTS_W TonemapMantiuk : public Tonemap + { + public: + CV_WRAP virtual float getScale() const = 0; + CV_WRAP virtual void setScale(float scale) = 0; - CV_WRAP virtual float getSaturation() const = 0; - CV_WRAP virtual void setSaturation(float saturation) = 0; -}; + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; + }; -CV_EXPORTS_W Ptr -createTonemapMantiuk(float gamma = 1.0f, float scale = 0.7f, float saturation = 1.0f); + CV_EXPORTS_W Ptr + createTonemapMantiuk(float gamma = 1.0f, float scale = 0.7f, float saturation = 1.0f); -class CV_EXPORTS_W AlignExposures : public Algorithm -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, - InputArray times, InputArray response) = 0; -}; + class CV_EXPORTS_W AlignExposures : public Algorithm + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, + InputArray times, InputArray response) = 0; + }; -// "Fast, Robust Image Registration for Compositing High Dynamic Range Photographs from Handheld Exposures", Ward, 2003 + // "Fast, Robust Image Registration for Compositing High Dynamic Range Photographs from Handheld Exposures", Ward, 2003 -class CV_EXPORTS_W AlignMTB : public AlignExposures -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, - InputArray times, InputArray response) = 0; + class CV_EXPORTS_W AlignMTB : public AlignExposures + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, + InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst) = 0; - CV_WRAP virtual Point calculateShift(InputArray img0, InputArray img1) = 0; - CV_WRAP virtual void shiftMat(InputArray src, OutputArray dst, const Point shift) = 0; - CV_WRAP virtual void computeBitmaps(InputArray img, OutputArray tb, OutputArray eb) = 0; + CV_WRAP virtual Point calculateShift(InputArray img0, InputArray img1) = 0; + CV_WRAP virtual void shiftMat(InputArray src, OutputArray dst, const Point shift) = 0; + CV_WRAP virtual void computeBitmaps(InputArray img, OutputArray tb, OutputArray eb) = 0; - CV_WRAP virtual int getMaxBits() const = 0; - CV_WRAP virtual void setMaxBits(int max_bits) = 0; + CV_WRAP virtual int getMaxBits() const = 0; + CV_WRAP virtual void setMaxBits(int max_bits) = 0; - CV_WRAP virtual int getExcludeRange() const = 0; - CV_WRAP virtual void setExcludeRange(int exclude_range) = 0; + CV_WRAP virtual int getExcludeRange() const = 0; + CV_WRAP virtual void setExcludeRange(int exclude_range) = 0; - CV_WRAP virtual bool getCut() const = 0; - CV_WRAP virtual void setCut(bool value) = 0; -}; + CV_WRAP virtual bool getCut() const = 0; + CV_WRAP virtual void setCut(bool value) = 0; + }; -CV_EXPORTS_W Ptr createAlignMTB(int max_bits = 6, int exclude_range = 4, bool cut = true); + CV_EXPORTS_W Ptr createAlignMTB(int max_bits = 6, int exclude_range = 4, bool cut = true); -class CV_EXPORTS_W CalibrateCRF : public Algorithm -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; -}; + class CV_EXPORTS_W CalibrateCRF : public Algorithm + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; + }; -// "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 + // "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 -class CV_EXPORTS_W CalibrateDebevec : public CalibrateCRF -{ -public: - CV_WRAP virtual float getLambda() const = 0; - CV_WRAP virtual void setLambda(float lambda) = 0; + class CV_EXPORTS_W CalibrateDebevec : public CalibrateCRF + { + public: + CV_WRAP virtual float getLambda() const = 0; + CV_WRAP virtual void setLambda(float lambda) = 0; - CV_WRAP virtual int getSamples() const = 0; - CV_WRAP virtual void setSamples(int samples) = 0; + CV_WRAP virtual int getSamples() const = 0; + CV_WRAP virtual void setSamples(int samples) = 0; - CV_WRAP virtual bool getRandom() const = 0; - CV_WRAP virtual void setRandom(bool random) = 0; -}; + CV_WRAP virtual bool getRandom() const = 0; + CV_WRAP virtual void setRandom(bool random) = 0; + }; -CV_EXPORTS_W Ptr createCalibrateDebevec(int samples = 70, float lambda = 10.0f, bool random = false); + CV_EXPORTS_W Ptr createCalibrateDebevec(int samples = 70, float lambda = 10.0f, bool random = false); -// "Dynamic range improvement through multiple exposures", Robertson et al., 1999 + // "Dynamic range improvement through multiple exposures", Robertson et al., 1999 -class CV_EXPORTS_W CalibrateRobertson : public CalibrateCRF -{ -public: - CV_WRAP virtual int getMaxIter() const = 0; - CV_WRAP virtual void setMaxIter(int max_iter) = 0; + class CV_EXPORTS_W CalibrateRobertson : public CalibrateCRF + { + public: + CV_WRAP virtual int getMaxIter() const = 0; + CV_WRAP virtual void setMaxIter(int max_iter) = 0; - CV_WRAP virtual float getThreshold() const = 0; - CV_WRAP virtual void setThreshold(float threshold) = 0; + CV_WRAP virtual float getThreshold() const = 0; + CV_WRAP virtual void setThreshold(float threshold) = 0; - CV_WRAP virtual Mat getRadiance() const = 0; -}; + CV_WRAP virtual Mat getRadiance() const = 0; + }; -CV_EXPORTS_W Ptr createCalibrateRobertson(int max_iter = 30, float threshold = 0.01f); + CV_EXPORTS_W Ptr createCalibrateRobertson(int max_iter = 30, float threshold = 0.01f); -class CV_EXPORTS_W MergeExposures : public Algorithm -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; -}; + class CV_EXPORTS_W MergeExposures : public Algorithm + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + }; -// "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 + // "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 -class CV_EXPORTS_W MergeDebevec : public MergeExposures -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; -}; + class CV_EXPORTS_W MergeDebevec : public MergeExposures + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; + }; -CV_EXPORTS_W Ptr createMergeDebevec(); + CV_EXPORTS_W Ptr createMergeDebevec(); -// "Exposure Fusion", Mertens et al., 2007 + // "Exposure Fusion", Mertens et al., 2007 -class CV_EXPORTS_W MergeMertens : public MergeExposures -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst) = 0; + class CV_EXPORTS_W MergeMertens : public MergeExposures + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst) = 0; - CV_WRAP virtual float getContrastWeight() const = 0; - CV_WRAP virtual void setContrastWeight(float contrast_weiht) = 0; + CV_WRAP virtual float getContrastWeight() const = 0; + CV_WRAP virtual void setContrastWeight(float contrast_weiht) = 0; - CV_WRAP virtual float getSaturationWeight() const = 0; - CV_WRAP virtual void setSaturationWeight(float saturation_weight) = 0; + CV_WRAP virtual float getSaturationWeight() const = 0; + CV_WRAP virtual void setSaturationWeight(float saturation_weight) = 0; - CV_WRAP virtual float getExposureWeight() const = 0; - CV_WRAP virtual void setExposureWeight(float exposure_weight) = 0; -}; + CV_WRAP virtual float getExposureWeight() const = 0; + CV_WRAP virtual void setExposureWeight(float exposure_weight) = 0; + }; -CV_EXPORTS_W Ptr -createMergeMertens(float contrast_weight = 1.0f, float saturation_weight = 1.0f, float exposure_weight = 0.0f); + CV_EXPORTS_W Ptr + createMergeMertens(float contrast_weight = 1.0f, float saturation_weight = 1.0f, float exposure_weight = 0.0f); -// "Dynamic range improvement through multiple exposures", Robertson et al., 1999 + // "Dynamic range improvement through multiple exposures", Robertson et al., 1999 -class CV_EXPORTS_W MergeRobertson : public MergeExposures -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; -}; + class CV_EXPORTS_W MergeRobertson : public MergeExposures + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; + }; -CV_EXPORTS_W Ptr createMergeRobertson(); + CV_EXPORTS_W Ptr createMergeRobertson(); CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost); @@ -328,9 +328,6 @@ CV_EXPORTS_W Ptr createMergeRobertson(); CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45); - CV_EXPORTS_W void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, - float sigma_r = 0.45); - } // cv #endif diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 6319d15513..54b9525af1 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -74,6 +74,13 @@ class Decolor void grayImContruct(vector &wei, Mat img, Mat &Gray); }; +int round_num(double a); + +int round_num(double a) +{ + return int(a + 0.5); +} + double Decolor::energyCalcu(vector &Cg, vector < vector > &polyGrad, vector &wei) { vector energy; @@ -228,7 +235,7 @@ void Decolor::weak_order(Mat img, vector &alf) if((h + w) > 800) { sizefactor = (double)800/(h+w); - resize(img,img,Size(round(h*sizefactor),round(w*sizefactor))); + resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor))); } Mat curIm = Mat(img.size(),CV_32FC1); @@ -304,7 +311,7 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, if((h + w) > 800) { sizefactor = (double)800/(h+w); - resize(img,img,Size(round(h*sizefactor),round(w*sizefactor))); + resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor))); } h = img.size().height; diff --git a/modules/photo/src/npr.cpp b/modules/photo/src/npr.cpp index a3b38d4ee1..3f0be9ba9f 100644 --- a/modules/photo/src/npr.cpp +++ b/modules/photo/src/npr.cpp @@ -151,7 +151,6 @@ void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sig int h = img.size().height; int w = img.size().width; - int channel = img.channels(); Mat res = Mat(h,w,CV_32FC3); Mat magnitude = Mat(h,w,CV_32FC1); @@ -159,7 +158,7 @@ void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sig Domain_Filter obj; obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); - obj.find_magnitude(res,magnitude,2); + obj.find_magnitude(res,magnitude); Mat stylized = Mat(h,w,CV_32FC3); @@ -172,31 +171,3 @@ void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sig stylized.convertTo(dst,CV_8UC3,255); } - -void cv::edgeEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) -{ - Mat I = _src.getMat(); - _dst.create(I.size(), CV_8UC1); - Mat dst = _dst.getMat(); - - Mat img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); - - Mat orig = img.clone(); - - int h = img.size().height; - int w = img.size().width; - - Mat res = Mat(h,w,CV_32FC3); - Mat magnitude = Mat(h,w,CV_32FC1); - - Mat mag8 = Mat(h,w,CV_32FC1); - - Domain_Filter obj; - - obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); - - obj.find_magnitude(res,magnitude,1); - - magnitude.convertTo(dst,CV_8UC1,255); -} diff --git a/modules/photo/src/npr.hpp b/modules/photo/src/npr.hpp index 733d418d58..9658e25a6b 100644 --- a/modules/photo/src/npr.hpp +++ b/modules/photo/src/npr.hpp @@ -61,7 +61,7 @@ class Domain_Filter void getGradienty( const Mat &img, Mat &gy); void diffx(const Mat &img, Mat &temp); void diffy(const Mat &img, Mat &temp); - void find_magnitude(Mat &img, Mat &mag, int flags); + void find_magnitude(Mat &img, Mat &mag); void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius); void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h); void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius); @@ -131,7 +131,7 @@ void Domain_Filter::getGradienty( const Mat &img, Mat &gy) } } -void Domain_Filter::find_magnitude(Mat &img, Mat &mag, int flags) +void Domain_Filter::find_magnitude(Mat &img, Mat &mag) { int h = img.rows; int w = img.cols; @@ -148,28 +148,14 @@ void Domain_Filter::find_magnitude(Mat &img, Mat &mag, int flags) Mat magXB = Mat(h, w, CV_32FC1); Mat magYB = Mat(h, w, CV_32FC1); - if(flags == 1) - { - getGradientx(planes[0], magXR); - getGradienty(planes[0], magYR); + Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); + Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); - getGradientx(planes[1], magXG); - getGradienty(planes[1], magYG); + Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); + Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); - getGradientx(planes[2], magXR); - getGradienty(planes[2], magYR); - } - else if(flags == 2) - { - Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); - Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); - - Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); - Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); - - Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); - Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); - } + Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); + Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); Mat mag1 = Mat(h,w,CV_32FC1); Mat mag2 = Mat(h,w,CV_32FC1); diff --git a/modules/photo/test/test_npr.cpp b/modules/photo/test/test_npr.cpp old mode 100644 new mode 100755 index 5d55d4c3b4..993f6c390f --- a/modules/photo/test/test_npr.cpp +++ b/modules/photo/test/test_npr.cpp @@ -128,19 +128,3 @@ TEST(Photo_NPR_Stylization, regression) imwrite(folder + "stylized.png", result); } - -TEST(Photo_NPR_EdgeEnhance, regression) -{ - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; - string original_path = folder + "test1.png"; - - Mat source = imread(original_path, IMREAD_COLOR); - - ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; - - Mat result; - edgeEnhance(source,result); - - imwrite(folder + "edge_enhanced.png", result); - -} diff --git a/samples/cpp/cloning_demo.cpp b/samples/cpp/cloning_demo.cpp index d9bcfb3eb6..7ff0100680 100644 --- a/samples/cpp/cloning_demo.cpp +++ b/samples/cpp/cloning_demo.cpp @@ -43,7 +43,7 @@ int main() cout << "6) Texture Flattening " << endl; cout << endl; cout << "Press number 1-6 to choose from above techniques: "; - int num; + int num = 1; cin >> num; cout << endl; diff --git a/samples/cpp/npr_demo.cpp b/samples/cpp/npr_demo.cpp index e5e2528f13..30d30cba9f 100644 --- a/samples/cpp/npr_demo.cpp +++ b/samples/cpp/npr_demo.cpp @@ -11,7 +11,6 @@ * 2) Detail Enhancement * 3) Pencil sketch/Color Pencil Drawing * 4) Stylization -* 5) Edge Enhancement * */ @@ -57,10 +56,9 @@ int main(int argc, char* argv[]) cout << "2) Detail Enhancement" << endl; cout << "3) Pencil sketch/Color Pencil Drawing" << endl; cout << "4) Stylization" << endl; - cout << "5) Edge Enhancement" << endl; cout << endl; - cout << "Press number 1-5 to choose from above techniques: "; + cout << "Press number 1-4 to choose from above techniques: "; cin >> num; @@ -94,11 +92,5 @@ int main(int argc, char* argv[]) stylization(I,img); imshow("Stylization",img); } - else if(num == 5) - { - edgeEnhance(I,img); - imshow("Edge Enhance",img); - } - waitKey(0); } From 573e8184151e261c687db6fda5581fbabfdda907 Mon Sep 17 00:00:00 2001 From: siddharth Date: Wed, 6 Nov 2013 20:29:01 +0530 Subject: [PATCH 39/97] New changes done and removed opencv_extra folder Removed opencv_extra folder inside opencv folder New changes done Removed test images --- modules/photo/src/contrast_preserve.hpp | 5 ++--- modules/photo/src/npr.hpp | 13 ++---------- modules/photo/src/seamless_cloning.hpp | 28 +++++++++---------------- 3 files changed, 14 insertions(+), 32 deletions(-) diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 54b9525af1..8a95170e32 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -427,7 +427,6 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) maxval = Gray.at(i,j); } - for(int i=0;i(i,j) = (Gray.at(i,j) - minval)/(maxval - minval); + Gray -= minval; + Gray /= maxval - minval; } diff --git a/modules/photo/src/npr.hpp b/modules/photo/src/npr.hpp index 9658e25a6b..744b2bdfbb 100644 --- a/modules/photo/src/npr.hpp +++ b/modules/photo/src/npr.hpp @@ -173,7 +173,6 @@ void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) { int h = output.rows; int w = output.cols; - int channel = output.channels(); float a = (float) exp((-1.0 * sqrt(2.0)) / sigma_h); @@ -190,11 +189,7 @@ void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) { for(int j =1; j < w; j++) { - for(int c = 0; c(i,j*channel+c) = temp.at(i,j*channel+c) + - (temp.at(i,(j-1)*channel+c) - temp.at(i,j*channel+c)) * V.at(i,j); - } + temp.at(i,j) = temp.at(i,j) + (temp.at(i,j-1) - temp.at(i,j)) * V.at(i,j); } } @@ -202,11 +197,7 @@ void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) { for(int j =w-2; j >= 0; j--) { - for(int c = 0; c(i,j*channel+c) = temp.at(i,j*channel+c) + - (temp.at(i,(j+1)*channel+c) - temp.at(i,j*channel+c))*V.at(i,j+1); - } + temp.at(i,j) = temp.at(i,j) + (temp.at(i,j+1) - temp.at(i,j)) * V.at(i,j+1); } } diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index 612d764d95..73d719c1ba 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -482,7 +482,6 @@ void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, int num) { int w = I.size().width; int h = I.size().height; - int channel = I.channels(); initialization(I,mask,wmask); @@ -496,25 +495,18 @@ void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, int num) { for(int i=0;i < h; i++) for(int j=0; j < w; j++) - for(int c=0;c(i,j) - sgy.at(i,j)) > abs(grx.at(i,j) - gry.at(i,j))) { - if(abs(sgx.at(i,j*channel+c) - sgy.at(i,j*channel+c)) > - abs(grx.at(i,j*channel+c) - gry.at(i,j*channel+c))) - { - - srx32.at(i,j*channel+c) = sgx.at(i,j*channel+c) - * smask.at(i,j); - sry32.at(i,j*channel+c) = sgy.at(i,j*channel+c) - * smask.at(i,j); - } - else - { - srx32.at(i,j*channel+c) = grx.at(i,j*channel+c) - * smask.at(i,j); - sry32.at(i,j*channel+c) = gry.at(i,j*channel+c) - * smask.at(i,j); - } + srx32.at(i,j) = sgx.at(i,j) * smask.at(i,j); + sry32.at(i,j) = sgy.at(i,j) * smask.at(i,j); } + else + { + srx32.at(i,j) = grx.at(i,j) * smask.at(i,j); + sry32.at(i,j) = gry.at(i,j) * smask.at(i,j); + } + } } else if(num == 3) { From 944f7bac42ac88dec6d92313720950fede6b373c Mon Sep 17 00:00:00 2001 From: Anna Kogan Date: Thu, 21 Nov 2013 15:45:53 +0400 Subject: [PATCH 40/97] After-merge corrections --- modules/photo/include/opencv2/photo.hpp | 403 ++++++++++++------------ 1 file changed, 203 insertions(+), 200 deletions(-) diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 949c1cfb62..b0e8e7d2be 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -52,281 +52,284 @@ namespace cv { - //! the inpainting algorithm - enum - { - INPAINT_NS = 0, // Navier-Stokes algorithm - INPAINT_TELEA = 1 // A. Telea algorithm - }; +//! the inpainting algorithm +enum +{ + INPAINT_NS = 0, // Navier-Stokes algorithm + INPAINT_TELEA = 1 // A. Telea algorithm +}; - enum - { - NORMAL_CLONE = 1, - MIXED_CLONE = 2, - MONOCHROME_TRANSFER = 3 - }; +enum +{ + NORMAL_CLONE = 1, + MIXED_CLONE = 2, + MONOCHROME_TRANSFER = 3 +}; - enum - { - RECURS_FILTER = 1, - NORMCONV_FILTER = 2 - }; +enum +{ + RECURS_FILTER = 1, + NORMCONV_FILTER = 2 +}; - //! restores the damaged image areas using one of the available intpainting algorithms - CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, - OutputArray dst, double inpaintRadius, int flags ); +//! restores the damaged image areas using one of the available intpainting algorithms +CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, + OutputArray dst, double inpaintRadius, int flags ); - CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3, - int templateWindowSize = 7, int searchWindowSize = 21); +CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3, + int templateWindowSize = 7, int searchWindowSize = 21); - CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst, - float h = 3, float hColor = 3, - int templateWindowSize = 7, int searchWindowSize = 21); +CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst, + float h = 3, float hColor = 3, + int templateWindowSize = 7, int searchWindowSize = 21); - CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst, - int imgToDenoiseIndex, int temporalWindowSize, - float h = 3, int templateWindowSize = 7, int searchWindowSize = 21); +CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst, + int imgToDenoiseIndex, int temporalWindowSize, + float h = 3, int templateWindowSize = 7, int searchWindowSize = 21); - CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst, - int imgToDenoiseIndex, int temporalWindowSize, - float h = 3, float hColor = 3, - int templateWindowSize = 7, int searchWindowSize = 21); +CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst, + int imgToDenoiseIndex, int temporalWindowSize, + float h = 3, float hColor = 3, + int templateWindowSize = 7, int searchWindowSize = 21); - enum { LDR_SIZE = 256 }; +enum { LDR_SIZE = 256 }; - class CV_EXPORTS_W Tonemap : public Algorithm - { - public: - CV_WRAP virtual void process(InputArray src, OutputArray dst) = 0; +class CV_EXPORTS_W Tonemap : public Algorithm +{ +public: + CV_WRAP virtual void process(InputArray src, OutputArray dst) = 0; - CV_WRAP virtual float getGamma() const = 0; - CV_WRAP virtual void setGamma(float gamma) = 0; - }; + CV_WRAP virtual float getGamma() const = 0; + CV_WRAP virtual void setGamma(float gamma) = 0; +}; - CV_EXPORTS_W Ptr createTonemap(float gamma = 1.0f); +CV_EXPORTS_W Ptr createTonemap(float gamma = 1.0f); - // "Adaptive Logarithmic Mapping For Displaying HighContrast Scenes", Drago et al., 2003 +// "Adaptive Logarithmic Mapping For Displaying HighContrast Scenes", Drago et al., 2003 - class CV_EXPORTS_W TonemapDrago : public Tonemap - { - public: +class CV_EXPORTS_W TonemapDrago : public Tonemap +{ +public: - CV_WRAP virtual float getSaturation() const = 0; - CV_WRAP virtual void setSaturation(float saturation) = 0; + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; - CV_WRAP virtual float getBias() const = 0; - CV_WRAP virtual void setBias(float bias) = 0; - }; + CV_WRAP virtual float getBias() const = 0; + CV_WRAP virtual void setBias(float bias) = 0; +}; - CV_EXPORTS_W Ptr createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f); +CV_EXPORTS_W Ptr createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f); - // "Fast Bilateral Filtering for the Display of High-Dynamic-Range Images", Durand, Dorsey, 2002 +// "Fast Bilateral Filtering for the Display of High-Dynamic-Range Images", Durand, Dorsey, 2002 - class CV_EXPORTS_W TonemapDurand : public Tonemap - { - public: +class CV_EXPORTS_W TonemapDurand : public Tonemap +{ +public: - CV_WRAP virtual float getSaturation() const = 0; - CV_WRAP virtual void setSaturation(float saturation) = 0; + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; - CV_WRAP virtual float getContrast() const = 0; - CV_WRAP virtual void setContrast(float contrast) = 0; + CV_WRAP virtual float getContrast() const = 0; + CV_WRAP virtual void setContrast(float contrast) = 0; - CV_WRAP virtual float getSigmaSpace() const = 0; - CV_WRAP virtual void setSigmaSpace(float sigma_space) = 0; + CV_WRAP virtual float getSigmaSpace() const = 0; + CV_WRAP virtual void setSigmaSpace(float sigma_space) = 0; - CV_WRAP virtual float getSigmaColor() const = 0; - CV_WRAP virtual void setSigmaColor(float sigma_color) = 0; - }; + CV_WRAP virtual float getSigmaColor() const = 0; + CV_WRAP virtual void setSigmaColor(float sigma_color) = 0; +}; - CV_EXPORTS_W Ptr - createTonemapDurand(float gamma = 1.0f, float contrast = 4.0f, float saturation = 1.0f, float sigma_space = 2.0f, float sigma_color = 2.0f); +CV_EXPORTS_W Ptr +createTonemapDurand(float gamma = 1.0f, float contrast = 4.0f, float saturation = 1.0f, float sigma_space = 2.0f, float sigma_color = 2.0f); - // "Dynamic Range Reduction Inspired by Photoreceptor Physiology", Reinhard, Devlin, 2005 +// "Dynamic Range Reduction Inspired by Photoreceptor Physiology", Reinhard, Devlin, 2005 - class CV_EXPORTS_W TonemapReinhard : public Tonemap - { - public: - CV_WRAP virtual float getIntensity() const = 0; - CV_WRAP virtual void setIntensity(float intensity) = 0; +class CV_EXPORTS_W TonemapReinhard : public Tonemap +{ +public: + CV_WRAP virtual float getIntensity() const = 0; + CV_WRAP virtual void setIntensity(float intensity) = 0; - CV_WRAP virtual float getLightAdaptation() const = 0; - CV_WRAP virtual void setLightAdaptation(float light_adapt) = 0; + CV_WRAP virtual float getLightAdaptation() const = 0; + CV_WRAP virtual void setLightAdaptation(float light_adapt) = 0; - CV_WRAP virtual float getColorAdaptation() const = 0; - CV_WRAP virtual void setColorAdaptation(float color_adapt) = 0; - }; + CV_WRAP virtual float getColorAdaptation() const = 0; + CV_WRAP virtual void setColorAdaptation(float color_adapt) = 0; +}; - CV_EXPORTS_W Ptr - createTonemapReinhard(float gamma = 1.0f, float intensity = 0.0f, float light_adapt = 1.0f, float color_adapt = 0.0f); +CV_EXPORTS_W Ptr +createTonemapReinhard(float gamma = 1.0f, float intensity = 0.0f, float light_adapt = 1.0f, float color_adapt = 0.0f); - // "Perceptual Framework for Contrast Processing of High Dynamic Range Images", Mantiuk et al., 2006 +// "Perceptual Framework for Contrast Processing of High Dynamic Range Images", Mantiuk et al., 2006 - class CV_EXPORTS_W TonemapMantiuk : public Tonemap - { - public: - CV_WRAP virtual float getScale() const = 0; - CV_WRAP virtual void setScale(float scale) = 0; +class CV_EXPORTS_W TonemapMantiuk : public Tonemap +{ +public: + CV_WRAP virtual float getScale() const = 0; + CV_WRAP virtual void setScale(float scale) = 0; - CV_WRAP virtual float getSaturation() const = 0; - CV_WRAP virtual void setSaturation(float saturation) = 0; - }; + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; +}; - CV_EXPORTS_W Ptr - createTonemapMantiuk(float gamma = 1.0f, float scale = 0.7f, float saturation = 1.0f); +CV_EXPORTS_W Ptr +createTonemapMantiuk(float gamma = 1.0f, float scale = 0.7f, float saturation = 1.0f); - class CV_EXPORTS_W AlignExposures : public Algorithm - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, - InputArray times, InputArray response) = 0; - }; +class CV_EXPORTS_W AlignExposures : public Algorithm +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, + InputArray times, InputArray response) = 0; +}; - // "Fast, Robust Image Registration for Compositing High Dynamic Range Photographs from Handheld Exposures", Ward, 2003 +// "Fast, Robust Image Registration for Compositing High Dynamic Range Photographs from Handheld Exposures", Ward, 2003 - class CV_EXPORTS_W AlignMTB : public AlignExposures - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, - InputArray times, InputArray response) = 0; +class CV_EXPORTS_W AlignMTB : public AlignExposures +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, + InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst) = 0; - CV_WRAP virtual Point calculateShift(InputArray img0, InputArray img1) = 0; - CV_WRAP virtual void shiftMat(InputArray src, OutputArray dst, const Point shift) = 0; - CV_WRAP virtual void computeBitmaps(InputArray img, OutputArray tb, OutputArray eb) = 0; + CV_WRAP virtual Point calculateShift(InputArray img0, InputArray img1) = 0; + CV_WRAP virtual void shiftMat(InputArray src, OutputArray dst, const Point shift) = 0; + CV_WRAP virtual void computeBitmaps(InputArray img, OutputArray tb, OutputArray eb) = 0; - CV_WRAP virtual int getMaxBits() const = 0; - CV_WRAP virtual void setMaxBits(int max_bits) = 0; + CV_WRAP virtual int getMaxBits() const = 0; + CV_WRAP virtual void setMaxBits(int max_bits) = 0; - CV_WRAP virtual int getExcludeRange() const = 0; - CV_WRAP virtual void setExcludeRange(int exclude_range) = 0; + CV_WRAP virtual int getExcludeRange() const = 0; + CV_WRAP virtual void setExcludeRange(int exclude_range) = 0; - CV_WRAP virtual bool getCut() const = 0; - CV_WRAP virtual void setCut(bool value) = 0; - }; + CV_WRAP virtual bool getCut() const = 0; + CV_WRAP virtual void setCut(bool value) = 0; +}; - CV_EXPORTS_W Ptr createAlignMTB(int max_bits = 6, int exclude_range = 4, bool cut = true); +CV_EXPORTS_W Ptr createAlignMTB(int max_bits = 6, int exclude_range = 4, bool cut = true); - class CV_EXPORTS_W CalibrateCRF : public Algorithm - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; - }; +class CV_EXPORTS_W CalibrateCRF : public Algorithm +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; +}; - // "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 +// "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 - class CV_EXPORTS_W CalibrateDebevec : public CalibrateCRF - { - public: - CV_WRAP virtual float getLambda() const = 0; - CV_WRAP virtual void setLambda(float lambda) = 0; +class CV_EXPORTS_W CalibrateDebevec : public CalibrateCRF +{ +public: + CV_WRAP virtual float getLambda() const = 0; + CV_WRAP virtual void setLambda(float lambda) = 0; - CV_WRAP virtual int getSamples() const = 0; - CV_WRAP virtual void setSamples(int samples) = 0; + CV_WRAP virtual int getSamples() const = 0; + CV_WRAP virtual void setSamples(int samples) = 0; - CV_WRAP virtual bool getRandom() const = 0; - CV_WRAP virtual void setRandom(bool random) = 0; - }; + CV_WRAP virtual bool getRandom() const = 0; + CV_WRAP virtual void setRandom(bool random) = 0; +}; - CV_EXPORTS_W Ptr createCalibrateDebevec(int samples = 70, float lambda = 10.0f, bool random = false); +CV_EXPORTS_W Ptr createCalibrateDebevec(int samples = 70, float lambda = 10.0f, bool random = false); - // "Dynamic range improvement through multiple exposures", Robertson et al., 1999 +// "Dynamic range improvement through multiple exposures", Robertson et al., 1999 - class CV_EXPORTS_W CalibrateRobertson : public CalibrateCRF - { - public: - CV_WRAP virtual int getMaxIter() const = 0; - CV_WRAP virtual void setMaxIter(int max_iter) = 0; +class CV_EXPORTS_W CalibrateRobertson : public CalibrateCRF +{ +public: + CV_WRAP virtual int getMaxIter() const = 0; + CV_WRAP virtual void setMaxIter(int max_iter) = 0; - CV_WRAP virtual float getThreshold() const = 0; - CV_WRAP virtual void setThreshold(float threshold) = 0; + CV_WRAP virtual float getThreshold() const = 0; + CV_WRAP virtual void setThreshold(float threshold) = 0; - CV_WRAP virtual Mat getRadiance() const = 0; - }; + CV_WRAP virtual Mat getRadiance() const = 0; +}; - CV_EXPORTS_W Ptr createCalibrateRobertson(int max_iter = 30, float threshold = 0.01f); +CV_EXPORTS_W Ptr createCalibrateRobertson(int max_iter = 30, float threshold = 0.01f); - class CV_EXPORTS_W MergeExposures : public Algorithm - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - }; +class CV_EXPORTS_W MergeExposures : public Algorithm +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; +}; - // "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 +// "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 - class CV_EXPORTS_W MergeDebevec : public MergeExposures - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; - }; +class CV_EXPORTS_W MergeDebevec : public MergeExposures +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; +}; - CV_EXPORTS_W Ptr createMergeDebevec(); +CV_EXPORTS_W Ptr createMergeDebevec(); - // "Exposure Fusion", Mertens et al., 2007 +// "Exposure Fusion", Mertens et al., 2007 - class CV_EXPORTS_W MergeMertens : public MergeExposures - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst) = 0; +class CV_EXPORTS_W MergeMertens : public MergeExposures +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst) = 0; - CV_WRAP virtual float getContrastWeight() const = 0; - CV_WRAP virtual void setContrastWeight(float contrast_weiht) = 0; + CV_WRAP virtual float getContrastWeight() const = 0; + CV_WRAP virtual void setContrastWeight(float contrast_weiht) = 0; - CV_WRAP virtual float getSaturationWeight() const = 0; - CV_WRAP virtual void setSaturationWeight(float saturation_weight) = 0; + CV_WRAP virtual float getSaturationWeight() const = 0; + CV_WRAP virtual void setSaturationWeight(float saturation_weight) = 0; - CV_WRAP virtual float getExposureWeight() const = 0; - CV_WRAP virtual void setExposureWeight(float exposure_weight) = 0; - }; + CV_WRAP virtual float getExposureWeight() const = 0; + CV_WRAP virtual void setExposureWeight(float exposure_weight) = 0; +}; - CV_EXPORTS_W Ptr - createMergeMertens(float contrast_weight = 1.0f, float saturation_weight = 1.0f, float exposure_weight = 0.0f); +CV_EXPORTS_W Ptr +createMergeMertens(float contrast_weight = 1.0f, float saturation_weight = 1.0f, float exposure_weight = 0.0f); - // "Dynamic range improvement through multiple exposures", Robertson et al., 1999 +// "Dynamic range improvement through multiple exposures", Robertson et al., 1999 - class CV_EXPORTS_W MergeRobertson : public MergeExposures - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; - }; +class CV_EXPORTS_W MergeRobertson : public MergeExposures +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; +}; - CV_EXPORTS_W Ptr createMergeRobertson(); +CV_EXPORTS_W Ptr createMergeRobertson(); - CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost); +CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost); - CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, - OutputArray blend, int flags); +CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, + OutputArray blend, int flags); - CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, - float green_mul = 1.0, float blue_mul = 1.0); +CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, + float green_mul = 1.0, float blue_mul = 1.0); - CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, - float alpha = 0.2, float beta = 0.4); +CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, + float alpha = 0.2, float beta = 0.4); - CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, - double low_threshold = 30, double high_threshold = 45, - int kernel_size = 3); +CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, + double low_threshold, double high_threshold, + int kernel_size); - CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, - float sigma_s = 60, float sigma_r = 0.4); +CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, + float sigma_s = 60, float sigma_r = 0.4); - CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, - float sigma_r = 0.15); +CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, + float sigma_r = 0.15); - CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, - float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); +CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, + float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); - CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, - float sigma_r = 0.45); +CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, + float sigma_r = 0.45); + +CV_EXPORTS_W void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, + float sigma_r = 0.45); } // cv From c48ad880f39ec5f36e7aa2c6bec8ff3fea375cc0 Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 22 Nov 2013 23:37:41 +0530 Subject: [PATCH 41/97] Errors resolved --- modules/photo/include/opencv2/photo.hpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index b0e8e7d2be..7ca933c3f6 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -313,8 +313,8 @@ CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArra float alpha = 0.2, float beta = 0.4); CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, - double low_threshold, double high_threshold, - int kernel_size); + double low_threshold = 30, double high_threshold = 45, + int kernel_size = 3); CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4); @@ -328,9 +328,6 @@ CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45); -CV_EXPORTS_W void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, - float sigma_r = 0.45); - } // cv #endif From 778edff9e1bf2606504f8bc804f34f26470b48b7 Mon Sep 17 00:00:00 2001 From: siddharth Date: Wed, 4 Dec 2013 19:12:43 +0530 Subject: [PATCH 42/97] Added comment in demo file --- samples/cpp/cloning_demo.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/samples/cpp/cloning_demo.cpp b/samples/cpp/cloning_demo.cpp index 7ff0100680..65a57f1497 100644 --- a/samples/cpp/cloning_demo.cpp +++ b/samples/cpp/cloning_demo.cpp @@ -16,6 +16,9 @@ * The program takes as input a source and a destination image (for 1-3 methods) * and ouputs the cloned image. +* +* Download test images from opencv_extra folder @github. +* */ #include "opencv2/photo.hpp" From 00300baa53a6f57c8f5c2c52c7e32d6077802417 Mon Sep 17 00:00:00 2001 From: Baichuan Su Date: Sat, 9 Nov 2013 08:42:39 +0800 Subject: [PATCH 43/97] Add OpenCL SVM paths for bagofwords_classification and points_classifier samples. --- samples/cpp/CMakeLists.txt | 8 +++++++ samples/cpp/bagofwords_classification.cpp | 20 +++++++++++++++++ samples/cpp/points_classifier.cpp | 27 ++++++++++++++++++++++- 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/samples/cpp/CMakeLists.txt b/samples/cpp/CMakeLists.txt index 4eabd09f0b..ebee5bd0a8 100644 --- a/samples/cpp/CMakeLists.txt +++ b/samples/cpp/CMakeLists.txt @@ -20,6 +20,10 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND) ocv_include_directories("${OpenCV_SOURCE_DIR}/modules/gpu/include") endif() + if(HAVE_opencv_ocl) + ocv_include_directories("${OpenCV_SOURCE_DIR}/modules/ocl/include") + endif() + if(CMAKE_COMPILER_IS_GNUCXX AND NOT ENABLE_NOISY_WARNINGS) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function") endif() @@ -47,6 +51,10 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND) target_link_libraries(${the_target} opencv_gpu) endif() + if(HAVE_opencv_ocl) + target_link_libraries(${the_target} opencv_ocl) + endif() + set_target_properties(${the_target} PROPERTIES OUTPUT_NAME "cpp-${sample_kind}-${name}" PROJECT_LABEL "(${sample_KIND}) ${name}") diff --git a/samples/cpp/bagofwords_classification.cpp b/samples/cpp/bagofwords_classification.cpp index 39342c4d32..9749b4a2f0 100644 --- a/samples/cpp/bagofwords_classification.cpp +++ b/samples/cpp/bagofwords_classification.cpp @@ -1,8 +1,12 @@ +#include "opencv2/opencv_modules.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/nonfree/nonfree.hpp" #include "opencv2/ml/ml.hpp" +#ifdef HAVE_OPENCV_OCL +#include "opencv2/ocl/ocl.hpp" +#endif #include #include @@ -2373,9 +2377,15 @@ static void setSVMTrainAutoParams( CvParamGrid& c_grid, CvParamGrid& gamma_grid, degree_grid.step = 0; } +#ifdef HAVE_OPENCV_OCL +static void trainSVMClassifier( cv::ocl::CvSVM_OCL& svm, const SVMTrainParamsExt& svmParamsExt, const string& objClassName, VocData& vocData, + Ptr& bowExtractor, const Ptr& fdetector, + const string& resPath ) +#else static void trainSVMClassifier( CvSVM& svm, const SVMTrainParamsExt& svmParamsExt, const string& objClassName, VocData& vocData, Ptr& bowExtractor, const Ptr& fdetector, const string& resPath ) +#endif { /* first check if a previously trained svm for the current class has been saved to file */ string svmFilename = resPath + svmsDir + "/" + objClassName + ".xml.gz"; @@ -2448,9 +2458,15 @@ static void trainSVMClassifier( CvSVM& svm, const SVMTrainParamsExt& svmParamsEx } } +#ifdef HAVE_OPENCV_OCL +static void computeConfidences( cv::ocl::CvSVM_OCL& svm, const string& objClassName, VocData& vocData, + Ptr& bowExtractor, const Ptr& fdetector, + const string& resPath ) +#else static void computeConfidences( CvSVM& svm, const string& objClassName, VocData& vocData, Ptr& bowExtractor, const Ptr& fdetector, const string& resPath ) +#endif { cout << "*** CALCULATING CONFIDENCES FOR CLASS " << objClassName << " ***" << endl; cout << "CALCULATING BOW VECTORS FOR TEST SET OF " << objClassName << "..." << endl; @@ -2589,7 +2605,11 @@ int main(int argc, char** argv) for( size_t classIdx = 0; classIdx < objClasses.size(); ++classIdx ) { // Train a classifier on train dataset +#ifdef HAVE_OPENCV_OCL + cv::ocl::CvSVM_OCL svm; +#else CvSVM svm; +#endif trainSVMClassifier( svm, svmTrainParamsExt, objClasses[classIdx], vocData, bowExtractor, featureDetector, resPath ); diff --git a/samples/cpp/points_classifier.cpp b/samples/cpp/points_classifier.cpp index e23b2768a9..ca6c0c6817 100644 --- a/samples/cpp/points_classifier.cpp +++ b/samples/cpp/points_classifier.cpp @@ -1,6 +1,10 @@ +#include "opencv2/opencv_modules.hpp" #include "opencv2/core/core.hpp" #include "opencv2/ml/ml.hpp" #include "opencv2/highgui/highgui.hpp" +#ifdef HAVE_OPENCV_OCL +#include "opencv2/ocl/ocl.hpp" +#endif #include @@ -133,7 +137,14 @@ static void find_decision_boundary_KNN( int K ) prepare_train_data( trainSamples, trainClasses ); // learn classifier +#ifdef HAVE_OPENCV_OCL + cv::ocl::KNearestNeighbour knnClassifier; + Mat temp, result; + knnClassifier.train(trainSamples, trainClasses, temp, false, K); + cv::ocl::oclMat testSample_ocl, reslut_ocl; +#else CvKNearest knnClassifier( trainSamples, trainClasses, Mat(), false, K ); +#endif Mat testSample( 1, 2, CV_32FC1 ); for( int y = 0; y < img.rows; y += testStep ) @@ -142,9 +153,19 @@ static void find_decision_boundary_KNN( int K ) { testSample.at(0) = (float)x; testSample.at(1) = (float)y; +#ifdef HAVE_OPENCV_OCL + testSample_ocl.upload(testSample); + + knnClassifier.find_nearest(testSample_ocl, K, reslut_ocl); + + reslut_ocl.download(result); + int response = saturate_cast(result.at(0)); + circle(imgDst, Point(x, y), 1, classColors[response]); +#else int response = (int)knnClassifier.find_nearest( testSample, K ); circle( imgDst, Point(x,y), 1, classColors[response] ); +#endif } } } @@ -159,7 +180,11 @@ static void find_decision_boundary_SVM( CvSVMParams params ) prepare_train_data( trainSamples, trainClasses ); // learn classifier +#ifdef HAVE_OPENCV_OCL + cv::ocl::CvSVM_OCL svmClassifier(trainSamples, trainClasses, Mat(), Mat(), params); +#else CvSVM svmClassifier( trainSamples, trainClasses, Mat(), Mat(), params ); +#endif Mat testSample( 1, 2, CV_32FC1 ); for( int y = 0; y < img.rows; y += testStep ) @@ -178,7 +203,7 @@ static void find_decision_boundary_SVM( CvSVMParams params ) for( int i = 0; i < svmClassifier.get_support_vector_count(); i++ ) { const float* supportVector = svmClassifier.get_support_vector(i); - circle( imgDst, Point(supportVector[0],supportVector[1]), 5, Scalar(255,255,255), -1 ); + circle( imgDst, Point(saturate_cast(supportVector[0]),saturate_cast(supportVector[1])), 5, CV_RGB(255,255,255), -1 ); } } From 2cf16db683add5c9a4775bf17c76b6e55abcd8ee Mon Sep 17 00:00:00 2001 From: Baichuan Su Date: Mon, 11 Nov 2013 11:46:07 +0800 Subject: [PATCH 44/97] Add Macro to decide using ocl method or not. --- samples/cpp/bagofwords_classification.cpp | 7 ++++--- samples/cpp/points_classifier.cpp | 8 +++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/samples/cpp/bagofwords_classification.cpp b/samples/cpp/bagofwords_classification.cpp index 9749b4a2f0..fbb312f930 100644 --- a/samples/cpp/bagofwords_classification.cpp +++ b/samples/cpp/bagofwords_classification.cpp @@ -5,6 +5,7 @@ #include "opencv2/nonfree/nonfree.hpp" #include "opencv2/ml/ml.hpp" #ifdef HAVE_OPENCV_OCL +#define _OCL_SVM_ 0 //select whether using ocl::svm method or not, default is not #include "opencv2/ocl/ocl.hpp" #endif @@ -2377,7 +2378,7 @@ static void setSVMTrainAutoParams( CvParamGrid& c_grid, CvParamGrid& gamma_grid, degree_grid.step = 0; } -#ifdef HAVE_OPENCV_OCL +#if defined HAVE_OPENCV_OCL && _OCL_SVM_ static void trainSVMClassifier( cv::ocl::CvSVM_OCL& svm, const SVMTrainParamsExt& svmParamsExt, const string& objClassName, VocData& vocData, Ptr& bowExtractor, const Ptr& fdetector, const string& resPath ) @@ -2458,7 +2459,7 @@ static void trainSVMClassifier( CvSVM& svm, const SVMTrainParamsExt& svmParamsEx } } -#ifdef HAVE_OPENCV_OCL +#if defined HAVE_OPENCV_OCL && _OCL_SVM_ static void computeConfidences( cv::ocl::CvSVM_OCL& svm, const string& objClassName, VocData& vocData, Ptr& bowExtractor, const Ptr& fdetector, const string& resPath ) @@ -2605,7 +2606,7 @@ int main(int argc, char** argv) for( size_t classIdx = 0; classIdx < objClasses.size(); ++classIdx ) { // Train a classifier on train dataset -#ifdef HAVE_OPENCV_OCL +#if defined HAVE_OPENCV_OCL && _OCL_SVM_ cv::ocl::CvSVM_OCL svm; #else CvSVM svm; diff --git a/samples/cpp/points_classifier.cpp b/samples/cpp/points_classifier.cpp index ca6c0c6817..b0dc0357c9 100644 --- a/samples/cpp/points_classifier.cpp +++ b/samples/cpp/points_classifier.cpp @@ -3,6 +3,8 @@ #include "opencv2/ml/ml.hpp" #include "opencv2/highgui/highgui.hpp" #ifdef HAVE_OPENCV_OCL +#define _OCL_KNN_ 0 // select whether using ocl::KNN method or not, default is not +#define _OCL_SVM_ 0 // select whether using ocl::svm method or not, default is not #include "opencv2/ocl/ocl.hpp" #endif @@ -137,7 +139,7 @@ static void find_decision_boundary_KNN( int K ) prepare_train_data( trainSamples, trainClasses ); // learn classifier -#ifdef HAVE_OPENCV_OCL +#if defined HAVE_OPENCV_OCL && _OCL_KNN_ cv::ocl::KNearestNeighbour knnClassifier; Mat temp, result; knnClassifier.train(trainSamples, trainClasses, temp, false, K); @@ -153,7 +155,7 @@ static void find_decision_boundary_KNN( int K ) { testSample.at(0) = (float)x; testSample.at(1) = (float)y; -#ifdef HAVE_OPENCV_OCL +#if defined HAVE_OPENCV_OCL && _OCL_KNN_ testSample_ocl.upload(testSample); knnClassifier.find_nearest(testSample_ocl, K, reslut_ocl); @@ -180,7 +182,7 @@ static void find_decision_boundary_SVM( CvSVMParams params ) prepare_train_data( trainSamples, trainClasses ); // learn classifier -#ifdef HAVE_OPENCV_OCL +#if defined HAVE_OPENCV_OCL && _OCL_SVM_ cv::ocl::CvSVM_OCL svmClassifier(trainSamples, trainClasses, Mat(), Mat(), params); #else CvSVM svmClassifier( trainSamples, trainClasses, Mat(), Mat(), params ); From 632b21e090a18e3ff8c06ce660f18431e7947719 Mon Sep 17 00:00:00 2001 From: Baichuan Su Date: Tue, 12 Nov 2013 13:13:25 +0800 Subject: [PATCH 45/97] Modify default setting, using ocl method when have ocl module --- samples/cpp/bagofwords_classification.cpp | 2 +- samples/cpp/points_classifier.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/cpp/bagofwords_classification.cpp b/samples/cpp/bagofwords_classification.cpp index fbb312f930..db194b536c 100644 --- a/samples/cpp/bagofwords_classification.cpp +++ b/samples/cpp/bagofwords_classification.cpp @@ -5,7 +5,7 @@ #include "opencv2/nonfree/nonfree.hpp" #include "opencv2/ml/ml.hpp" #ifdef HAVE_OPENCV_OCL -#define _OCL_SVM_ 0 //select whether using ocl::svm method or not, default is not +#define _OCL_SVM_ 1 //select whether using ocl::svm method or not, default is using #include "opencv2/ocl/ocl.hpp" #endif diff --git a/samples/cpp/points_classifier.cpp b/samples/cpp/points_classifier.cpp index b0dc0357c9..b7e890d17b 100644 --- a/samples/cpp/points_classifier.cpp +++ b/samples/cpp/points_classifier.cpp @@ -3,8 +3,8 @@ #include "opencv2/ml/ml.hpp" #include "opencv2/highgui/highgui.hpp" #ifdef HAVE_OPENCV_OCL -#define _OCL_KNN_ 0 // select whether using ocl::KNN method or not, default is not -#define _OCL_SVM_ 0 // select whether using ocl::svm method or not, default is not +#define _OCL_KNN_ 1 // select whether using ocl::KNN method or not, default is using +#define _OCL_SVM_ 1 // select whether using ocl::svm method or not, default is using #include "opencv2/ocl/ocl.hpp" #endif From ff8738520147707d7fad1a19c926530453f942b5 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Wed, 4 Dec 2013 19:00:39 +0400 Subject: [PATCH 46/97] refactored CascadeClassifier to hide implementation details (take 2) --- .../objdetect/include/opencv2/objdetect.hpp | 195 +++++++----------- modules/objdetect/src/cascadedetect.cpp | 172 ++++++++++++--- modules/objdetect/src/cascadedetect.hpp | 178 +++++++++++++--- modules/ocl/src/haar.cpp | 2 +- 4 files changed, 369 insertions(+), 178 deletions(-) diff --git a/modules/objdetect/include/opencv2/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect.hpp index c3dee4a2bb..26419bc596 100644 --- a/modules/objdetect/include/opencv2/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect.hpp @@ -149,143 +149,96 @@ enum { CASCADE_DO_CANNY_PRUNING = 1, CASCADE_DO_ROUGH_SEARCH = 8 }; -class CV_EXPORTS_W CascadeClassifier +class CV_EXPORTS_W BaseCascadeClassifier : public Algorithm { public: - CV_WRAP CascadeClassifier(); - CV_WRAP CascadeClassifier( const String& filename ); - virtual ~CascadeClassifier(); + virtual ~BaseCascadeClassifier(); + virtual bool empty() const = 0; + virtual bool load( const String& filename ) = 0; + virtual void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + double scaleFactor, + int minNeighbors, int flags, + Size minSize, Size maxSize ) = 0; - CV_WRAP virtual bool empty() const; - CV_WRAP bool load( const String& filename ); - virtual bool read( const FileNode& node ); - CV_WRAP virtual void detectMultiScale( InputArray image, - CV_OUT std::vector& objects, - double scaleFactor = 1.1, - int minNeighbors = 3, int flags = 0, - Size minSize = Size(), - Size maxSize = Size() ); + virtual void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + CV_OUT std::vector& numDetections, + double scaleFactor, + int minNeighbors, int flags, + Size minSize, Size maxSize ) = 0; - CV_WRAP virtual void detectMultiScale( InputArray image, - CV_OUT std::vector& objects, - CV_OUT std::vector& numDetections, - double scaleFactor=1.1, - int minNeighbors=3, int flags=0, - Size minSize=Size(), - Size maxSize=Size() ); - - CV_WRAP virtual void detectMultiScale( InputArray image, + virtual void detectMultiScale( InputArray image, CV_OUT std::vector& objects, CV_OUT std::vector& rejectLevels, CV_OUT std::vector& levelWeights, - double scaleFactor = 1.1, - int minNeighbors = 3, int flags = 0, - Size minSize = Size(), - Size maxSize = Size(), - bool outputRejectLevels = false ); + double scaleFactor, + int minNeighbors, int flags, + Size minSize, Size maxSize, + bool outputRejectLevels ) = 0; + virtual bool isOldFormatCascade() const = 0; + virtual Size getOriginalWindowSize() const = 0; + virtual int getFeatureType() const = 0; + virtual void* getOldCascade() = 0; - bool isOldFormatCascade() const; - virtual Size getOriginalWindowSize() const; - int getFeatureType() const; - bool setImage( const Mat& ); - -protected: - virtual bool detectSingleScale( const Mat& image, int stripCount, Size processingRectSize, - int stripSize, int yStep, double factor, std::vector& candidates, - std::vector& rejectLevels, std::vector& levelWeights, bool outputRejectLevels = false ); - - virtual void detectMultiScaleNoGrouping( const Mat& image, std::vector& candidates, - std::vector& rejectLevels, std::vector& levelWeights, - double scaleFactor, Size minObjectSize, Size maxObjectSize, - bool outputRejectLevels = false ); - -protected: - enum { BOOST = 0 - }; - enum { DO_CANNY_PRUNING = CASCADE_DO_CANNY_PRUNING, - SCALE_IMAGE = CASCADE_SCALE_IMAGE, - FIND_BIGGEST_OBJECT = CASCADE_FIND_BIGGEST_OBJECT, - DO_ROUGH_SEARCH = CASCADE_DO_ROUGH_SEARCH - }; - - friend class CascadeClassifierInvoker; - - template - friend int predictOrdered( CascadeClassifier& cascade, Ptr &featureEvaluator, double& weight); - - template - friend int predictCategorical( CascadeClassifier& cascade, Ptr &featureEvaluator, double& weight); - - template - friend int predictOrderedStump( CascadeClassifier& cascade, Ptr &featureEvaluator, double& weight); - - template - friend int predictCategoricalStump( CascadeClassifier& cascade, Ptr &featureEvaluator, double& weight); - - bool setImage( Ptr& feval, const Mat& image); - virtual int runAt( Ptr& feval, Point pt, double& weight ); - - class Data - { - public: - struct CV_EXPORTS DTreeNode - { - int featureIdx; - float threshold; // for ordered features only - int left; - int right; - }; - - struct CV_EXPORTS DTree - { - int nodeCount; - }; - - struct CV_EXPORTS Stage - { - int first; - int ntrees; - float threshold; - }; - - bool read(const FileNode &node); - - bool isStumpBased; - - int stageType; - int featureType; - int ncategories; - Size origWinSize; - - std::vector stages; - std::vector classifiers; - std::vector nodes; - std::vector leaves; - std::vector subsets; - }; - - Data data; - Ptr featureEvaluator; - Ptr oldCascade; - -public: class CV_EXPORTS MaskGenerator { public: virtual ~MaskGenerator() {} - virtual cv::Mat generateMask(const cv::Mat& src)=0; - virtual void initializeMask(const cv::Mat& /*src*/) {}; + virtual Mat generateMask(const Mat& src)=0; + virtual void initializeMask(const Mat& /*src*/) {}; }; - void setMaskGenerator(Ptr maskGenerator); - Ptr getMaskGenerator(); - - void setFaceDetectionMaskGenerator(); - -protected: - Ptr maskGenerator; + virtual void setMaskGenerator(const Ptr& maskGenerator) = 0; + virtual Ptr getMaskGenerator() = 0; }; +class CV_EXPORTS_W CascadeClassifier : public BaseCascadeClassifier +{ +public: + CV_WRAP CascadeClassifier(); + CV_WRAP explicit CascadeClassifier(const String& filename); + virtual ~CascadeClassifier(); + CV_WRAP virtual bool empty() const; + CV_WRAP virtual bool load( const String& filename ); + CV_WRAP virtual void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + double scaleFactor = 1.1, + int minNeighbors = 3, int flags = 0, + Size minSize = Size(), + Size maxSize = Size() ); + + CV_WRAP virtual void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + CV_OUT std::vector& numDetections, + double scaleFactor=1.1, + int minNeighbors=3, int flags=0, + Size minSize=Size(), + Size maxSize=Size() ); + + CV_WRAP virtual void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + CV_OUT std::vector& rejectLevels, + CV_OUT std::vector& levelWeights, + double scaleFactor = 1.1, + int minNeighbors = 3, int flags = 0, + Size minSize = Size(), + Size maxSize = Size(), + bool outputRejectLevels = false ); + + CV_WRAP virtual bool isOldFormatCascade() const; + CV_WRAP virtual Size getOriginalWindowSize() const; + CV_WRAP virtual int getFeatureType() const; + virtual void* getOldCascade(); + + virtual void setMaskGenerator(const Ptr& maskGenerator); + virtual Ptr getMaskGenerator(); +protected: + Ptr cc; +}; + +CV_EXPORTS Ptr createFaceDetectionMaskGenerator(); + //////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector ////////////// // struct for detection region of interest (ROI) diff --git a/modules/objdetect/src/cascadedetect.cpp b/modules/objdetect/src/cascadedetect.cpp index 92b685c5dd..10c1b17a3c 100644 --- a/modules/objdetect/src/cascadedetect.cpp +++ b/modules/objdetect/src/cascadedetect.cpp @@ -430,7 +430,6 @@ void groupRectangles_meanshift(std::vector& rectList, std::vector& } - FeatureEvaluator::~FeatureEvaluator() {} bool FeatureEvaluator::read(const FileNode&) {return true;} Ptr FeatureEvaluator::clone() const { return Ptr(); } @@ -834,25 +833,20 @@ Ptr FeatureEvaluator::create( int featureType ) //---------------------------------------- Classifier Cascade -------------------------------------------- -CascadeClassifier::CascadeClassifier() +CascadeClassifierImpl::CascadeClassifierImpl() { } -CascadeClassifier::CascadeClassifier(const String& filename) -{ - load(filename); -} - -CascadeClassifier::~CascadeClassifier() +CascadeClassifierImpl::~CascadeClassifierImpl() { } -bool CascadeClassifier::empty() const +bool CascadeClassifierImpl::empty() const { return !oldCascade && data.stages.empty(); } -bool CascadeClassifier::load(const String& filename) +bool CascadeClassifierImpl::load(const String& filename) { oldCascade.release(); data = Data(); @@ -862,7 +856,7 @@ bool CascadeClassifier::load(const String& filename) if( !fs.isOpened() ) return false; - if( read(fs.getFirstTopLevelNode()) ) + if( read_(fs.getFirstTopLevelNode()) ) return true; fs.release(); @@ -871,7 +865,12 @@ bool CascadeClassifier::load(const String& filename) return !oldCascade.empty(); } -int CascadeClassifier::runAt( Ptr& evaluator, Point pt, double& weight ) +void CascadeClassifierImpl::read(const FileNode& node) +{ + read_(node); +} + +int CascadeClassifierImpl::runAt( Ptr& evaluator, Point pt, double& weight ) { CV_Assert( !oldCascade ); @@ -905,33 +904,33 @@ int CascadeClassifier::runAt( Ptr& evaluator, Point pt, double } } -bool CascadeClassifier::setImage( Ptr& evaluator, const Mat& image ) +bool CascadeClassifierImpl::setImage( Ptr& evaluator, const Mat& image ) { return empty() ? false : evaluator->setImage(image, data.origWinSize); } -void CascadeClassifier::setMaskGenerator(Ptr _maskGenerator) +void CascadeClassifierImpl::setMaskGenerator(const Ptr& _maskGenerator) { maskGenerator=_maskGenerator; } -Ptr CascadeClassifier::getMaskGenerator() +Ptr CascadeClassifierImpl::getMaskGenerator() { return maskGenerator; } -void CascadeClassifier::setFaceDetectionMaskGenerator() +Ptr createFaceDetectionMaskGenerator() { #ifdef HAVE_TEGRA_OPTIMIZATION - setMaskGenerator(tegra::getCascadeClassifierMaskGenerator(*this)); + return tegra::getCascadeClassifierMaskGenerator(*this); #else - setMaskGenerator(Ptr()); + return Ptr(); #endif } class CascadeClassifierInvoker : public ParallelLoopBody { public: - CascadeClassifierInvoker( CascadeClassifier& _cc, Size _sz1, int _stripSize, int _yStep, double _factor, + CascadeClassifierInvoker( CascadeClassifierImpl& _cc, Size _sz1, int _stripSize, int _yStep, double _factor, std::vector& _vec, std::vector& _levels, std::vector& _weights, bool outputLevels, const Mat& _mask, Mutex* _mtx) { classifier = &_cc; @@ -950,7 +949,8 @@ public: { Ptr evaluator = classifier->featureEvaluator->clone(); - Size winSize(cvRound(classifier->data.origWinSize.width * scalingFactor), cvRound(classifier->data.origWinSize.height * scalingFactor)); + Size winSize(cvRound(classifier->data.origWinSize.width * scalingFactor), + cvRound(classifier->data.origWinSize.height * scalingFactor)); int y1 = range.start * stripSize; int y2 = std::min(range.end * stripSize, processingRectSize.height); @@ -995,7 +995,7 @@ public: } } - CascadeClassifier* classifier; + CascadeClassifierImpl* classifier; std::vector* rectangles; Size processingRectSize; int stripSize, yStep; @@ -1010,7 +1010,7 @@ struct getRect { Rect operator ()(const CvAvgComp& e) const { return e.rect; } } struct getNeighbors { int operator ()(const CvAvgComp& e) const { return e.neighbors; } }; -bool CascadeClassifier::detectSingleScale( const Mat& image, int stripCount, Size processingRectSize, +bool CascadeClassifierImpl::detectSingleScale( const Mat& image, int stripCount, Size processingRectSize, int stripSize, int yStep, double factor, std::vector& candidates, std::vector& levels, std::vector& weights, bool outputRejectLevels ) { @@ -1051,27 +1051,33 @@ bool CascadeClassifier::detectSingleScale( const Mat& image, int stripCount, Siz return true; } -bool CascadeClassifier::isOldFormatCascade() const +bool CascadeClassifierImpl::isOldFormatCascade() const { return !oldCascade.empty(); } -int CascadeClassifier::getFeatureType() const +int CascadeClassifierImpl::getFeatureType() const { return featureEvaluator->getFeatureType(); } -Size CascadeClassifier::getOriginalWindowSize() const +Size CascadeClassifierImpl::getOriginalWindowSize() const { return data.origWinSize; } -bool CascadeClassifier::setImage(const Mat& image) +bool CascadeClassifierImpl::setImage(InputArray _image) { + Mat image = _image.getMat(); return featureEvaluator->setImage(image, data.origWinSize); } +void* CascadeClassifierImpl::getOldCascade() +{ + return oldCascade; +} + static void detectMultiScaleOldFormat( const Mat& image, Ptr oldCascade, std::vector& objects, std::vector& rejectLevels, @@ -1090,7 +1096,7 @@ static void detectMultiScaleOldFormat( const Mat& image, Ptr& candidates, +void CascadeClassifierImpl::detectMultiScaleNoGrouping( const Mat& image, std::vector& candidates, std::vector& rejectLevels, std::vector& levelWeights, double scaleFactor, Size minObjectSize, Size maxObjectSize, bool outputRejectLevels ) @@ -1154,7 +1160,7 @@ void CascadeClassifier::detectMultiScaleNoGrouping( const Mat& image, std::vecto } } -void CascadeClassifier::detectMultiScale( InputArray _image, std::vector& objects, +void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector& objects, std::vector& rejectLevels, std::vector& levelWeights, double scaleFactor, int minNeighbors, @@ -1189,7 +1195,7 @@ void CascadeClassifier::detectMultiScale( InputArray _image, std::vector& } } -void CascadeClassifier::detectMultiScale( InputArray _image, std::vector& objects, +void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector& objects, double scaleFactor, int minNeighbors, int flags, Size minObjectSize, Size maxObjectSize) { @@ -1200,7 +1206,7 @@ void CascadeClassifier::detectMultiScale( InputArray _image, std::vector& minNeighbors, flags, minObjectSize, maxObjectSize ); } -void CascadeClassifier::detectMultiScale( InputArray _image, std::vector& objects, +void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector& objects, std::vector& numDetections, double scaleFactor, int minNeighbors, int flags, Size minObjectSize, Size maxObjectSize ) @@ -1229,7 +1235,7 @@ void CascadeClassifier::detectMultiScale( InputArray _image, std::vector& } } -bool CascadeClassifier::Data::read(const FileNode &root) +bool CascadeClassifierImpl::Data::read(const FileNode &root) { static const float THRESHOLD_EPS = 1e-5f; @@ -1339,7 +1345,7 @@ bool CascadeClassifier::Data::read(const FileNode &root) return true; } -bool CascadeClassifier::read(const FileNode& root) +bool CascadeClassifierImpl::read_(const FileNode& root) { if( !data.read(root) ) return false; @@ -1356,4 +1362,106 @@ bool CascadeClassifier::read(const FileNode& root) template<> void DefaultDeleter::operator ()(CvHaarClassifierCascade* obj) const { cvReleaseHaarClassifierCascade(&obj); } + +BaseCascadeClassifier::~BaseCascadeClassifier() +{ +} + +CascadeClassifier::CascadeClassifier() {} +CascadeClassifier::CascadeClassifier(const String& filename) +{ + load(filename); +} + +CascadeClassifier::~CascadeClassifier() +{ +} + +bool CascadeClassifier::empty() const +{ + return cc.empty() || cc->empty(); +} + +bool CascadeClassifier::load( const String& filename ) +{ + cc = makePtr(); + if(!cc->load(filename)) + cc.release(); + return !empty(); +} + +void CascadeClassifier::detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + double scaleFactor, + int minNeighbors, int flags, + Size minSize, + Size maxSize ) +{ + CV_Assert(!empty()); + cc->detectMultiScale(image, objects, scaleFactor, minNeighbors, flags, minSize, maxSize); +} + +void CascadeClassifier::detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + CV_OUT std::vector& numDetections, + double scaleFactor, + int minNeighbors, int flags, + Size minSize, Size maxSize ) +{ + CV_Assert(!empty()); + cc->detectMultiScale(image, objects, numDetections, + scaleFactor, minNeighbors, flags, minSize, maxSize); +} + +void CascadeClassifier::detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + CV_OUT std::vector& rejectLevels, + CV_OUT std::vector& levelWeights, + double scaleFactor, + int minNeighbors, int flags, + Size minSize, Size maxSize, + bool outputRejectLevels ) +{ + CV_Assert(!empty()); + cc->detectMultiScale(image, objects, rejectLevels, levelWeights, + scaleFactor, minNeighbors, flags, + minSize, maxSize, outputRejectLevels); +} + +bool CascadeClassifier::isOldFormatCascade() const +{ + CV_Assert(!empty()); + return cc->isOldFormatCascade(); +} + +Size CascadeClassifier::getOriginalWindowSize() const +{ + CV_Assert(!empty()); + return cc->getOriginalWindowSize(); +} + +int CascadeClassifier::getFeatureType() const +{ + CV_Assert(!empty()); + return cc->getFeatureType(); +} + +void* CascadeClassifier::getOldCascade() +{ + CV_Assert(!empty()); + return cc->getOldCascade(); +} + +void CascadeClassifier::setMaskGenerator(const Ptr& maskGenerator) +{ + CV_Assert(!empty()); + cc->setMaskGenerator(maskGenerator); +} + +Ptr CascadeClassifier::getMaskGenerator() +{ + CV_Assert(!empty()); + return cc->getMaskGenerator(); +} + } // namespace cv diff --git a/modules/objdetect/src/cascadedetect.hpp b/modules/objdetect/src/cascadedetect.hpp index de3303e4aa..862a273dcf 100644 --- a/modules/objdetect/src/cascadedetect.hpp +++ b/modules/objdetect/src/cascadedetect.hpp @@ -3,6 +3,132 @@ namespace cv { +class CascadeClassifierImpl : public BaseCascadeClassifier +{ +public: + CascadeClassifierImpl(); + virtual ~CascadeClassifierImpl(); + + bool empty() const; + bool load( const String& filename ); + void read( const FileNode& node ); + bool read_( const FileNode& node ); + void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + double scaleFactor = 1.1, + int minNeighbors = 3, int flags = 0, + Size minSize = Size(), + Size maxSize = Size() ); + + void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + CV_OUT std::vector& numDetections, + double scaleFactor=1.1, + int minNeighbors=3, int flags=0, + Size minSize=Size(), + Size maxSize=Size() ); + + void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + CV_OUT std::vector& rejectLevels, + CV_OUT std::vector& levelWeights, + double scaleFactor = 1.1, + int minNeighbors = 3, int flags = 0, + Size minSize = Size(), + Size maxSize = Size(), + bool outputRejectLevels = false ); + + + bool isOldFormatCascade() const; + Size getOriginalWindowSize() const; + int getFeatureType() const; + bool setImage( InputArray ); + void* getOldCascade(); + + void setMaskGenerator(const Ptr& maskGenerator); + Ptr getMaskGenerator(); + +protected: + bool detectSingleScale( const Mat& image, int stripCount, Size processingRectSize, + int stripSize, int yStep, double factor, std::vector& candidates, + std::vector& rejectLevels, std::vector& levelWeights, bool outputRejectLevels = false ); + + void detectMultiScaleNoGrouping( const Mat& image, std::vector& candidates, + std::vector& rejectLevels, std::vector& levelWeights, + double scaleFactor, Size minObjectSize, Size maxObjectSize, + bool outputRejectLevels = false ); + + enum { BOOST = 0 + }; + enum { DO_CANNY_PRUNING = CASCADE_DO_CANNY_PRUNING, + SCALE_IMAGE = CASCADE_SCALE_IMAGE, + FIND_BIGGEST_OBJECT = CASCADE_FIND_BIGGEST_OBJECT, + DO_ROUGH_SEARCH = CASCADE_DO_ROUGH_SEARCH + }; + + friend class CascadeClassifierInvoker; + + template + friend int predictOrdered( CascadeClassifierImpl& cascade, Ptr &featureEvaluator, double& weight); + + template + friend int predictCategorical( CascadeClassifierImpl& cascade, Ptr &featureEvaluator, double& weight); + + template + friend int predictOrderedStump( CascadeClassifierImpl& cascade, Ptr &featureEvaluator, double& weight); + + template + friend int predictCategoricalStump( CascadeClassifierImpl& cascade, Ptr &featureEvaluator, double& weight); + + bool setImage( Ptr& feval, const Mat& image); + int runAt( Ptr& feval, Point pt, double& weight ); + + class Data + { + public: + struct CV_EXPORTS DTreeNode + { + int featureIdx; + float threshold; // for ordered features only + int left; + int right; + }; + + struct CV_EXPORTS DTree + { + int nodeCount; + }; + + struct CV_EXPORTS Stage + { + int first; + int ntrees; + float threshold; + }; + + bool read(const FileNode &node); + + bool isStumpBased; + + int stageType; + int featureType; + int ncategories; + Size origWinSize; + + std::vector stages; + std::vector classifiers; + std::vector nodes; + std::vector leaves; + std::vector subsets; + }; + + Data data; + Ptr featureEvaluator; + Ptr oldCascade; + + Ptr maskGenerator; +}; + #define CC_CASCADE_PARAMS "cascadeParams" #define CC_STAGE_TYPE "stageType" #define CC_FEATURE_TYPE "featureType" @@ -322,30 +448,31 @@ inline void HOGEvaluator::Feature :: updatePtrs( const std::vector &_hist, //---------------------------------------------- predictor functions ------------------------------------- template -inline int predictOrdered( CascadeClassifier& cascade, Ptr &_featureEvaluator, double& sum ) +inline int predictOrdered( CascadeClassifierImpl& cascade, + Ptr &_featureEvaluator, double& sum ) { int nstages = (int)cascade.data.stages.size(); int nodeOfs = 0, leafOfs = 0; FEval& featureEvaluator = (FEval&)*_featureEvaluator; float* cascadeLeaves = &cascade.data.leaves[0]; - CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0]; - CascadeClassifier::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0]; - CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0]; + CascadeClassifierImpl::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0]; + CascadeClassifierImpl::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0]; + CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0]; for( int si = 0; si < nstages; si++ ) { - CascadeClassifier::Data::Stage& stage = cascadeStages[si]; + CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si]; int wi, ntrees = stage.ntrees; sum = 0; for( wi = 0; wi < ntrees; wi++ ) { - CascadeClassifier::Data::DTree& weak = cascadeWeaks[stage.first + wi]; + CascadeClassifierImpl::Data::DTree& weak = cascadeWeaks[stage.first + wi]; int idx = 0, root = nodeOfs; do { - CascadeClassifier::Data::DTreeNode& node = cascadeNodes[root + idx]; + CascadeClassifierImpl::Data::DTreeNode& node = cascadeNodes[root + idx]; double val = featureEvaluator(node.featureIdx); idx = val < node.threshold ? node.left : node.right; } @@ -361,7 +488,8 @@ inline int predictOrdered( CascadeClassifier& cascade, Ptr &_f } template -inline int predictCategorical( CascadeClassifier& cascade, Ptr &_featureEvaluator, double& sum ) +inline int predictCategorical( CascadeClassifierImpl& cascade, + Ptr &_featureEvaluator, double& sum ) { int nstages = (int)cascade.data.stages.size(); int nodeOfs = 0, leafOfs = 0; @@ -369,23 +497,23 @@ inline int predictCategorical( CascadeClassifier& cascade, Ptr size_t subsetSize = (cascade.data.ncategories + 31)/32; int* cascadeSubsets = &cascade.data.subsets[0]; float* cascadeLeaves = &cascade.data.leaves[0]; - CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0]; - CascadeClassifier::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0]; - CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0]; + CascadeClassifierImpl::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0]; + CascadeClassifierImpl::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0]; + CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0]; for(int si = 0; si < nstages; si++ ) { - CascadeClassifier::Data::Stage& stage = cascadeStages[si]; + CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si]; int wi, ntrees = stage.ntrees; sum = 0; for( wi = 0; wi < ntrees; wi++ ) { - CascadeClassifier::Data::DTree& weak = cascadeWeaks[stage.first + wi]; + CascadeClassifierImpl::Data::DTree& weak = cascadeWeaks[stage.first + wi]; int idx = 0, root = nodeOfs; do { - CascadeClassifier::Data::DTreeNode& node = cascadeNodes[root + idx]; + CascadeClassifierImpl::Data::DTreeNode& node = cascadeNodes[root + idx]; int c = featureEvaluator(node.featureIdx); const int* subset = &cascadeSubsets[(root + idx)*subsetSize]; idx = (subset[c>>5] & (1 << (c & 31))) ? node.left : node.right; @@ -402,24 +530,25 @@ inline int predictCategorical( CascadeClassifier& cascade, Ptr } template -inline int predictOrderedStump( CascadeClassifier& cascade, Ptr &_featureEvaluator, double& sum ) +inline int predictOrderedStump( CascadeClassifierImpl& cascade, + Ptr &_featureEvaluator, double& sum ) { int nodeOfs = 0, leafOfs = 0; FEval& featureEvaluator = (FEval&)*_featureEvaluator; float* cascadeLeaves = &cascade.data.leaves[0]; - CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0]; - CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0]; + CascadeClassifierImpl::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0]; + CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0]; int nstages = (int)cascade.data.stages.size(); for( int stageIdx = 0; stageIdx < nstages; stageIdx++ ) { - CascadeClassifier::Data::Stage& stage = cascadeStages[stageIdx]; + CascadeClassifierImpl::Data::Stage& stage = cascadeStages[stageIdx]; sum = 0.0; int ntrees = stage.ntrees; for( int i = 0; i < ntrees; i++, nodeOfs++, leafOfs+= 2 ) { - CascadeClassifier::Data::DTreeNode& node = cascadeNodes[nodeOfs]; + CascadeClassifierImpl::Data::DTreeNode& node = cascadeNodes[nodeOfs]; double value = featureEvaluator(node.featureIdx); sum += cascadeLeaves[ value < node.threshold ? leafOfs : leafOfs + 1 ]; } @@ -432,7 +561,8 @@ inline int predictOrderedStump( CascadeClassifier& cascade, Ptr -inline int predictCategoricalStump( CascadeClassifier& cascade, Ptr &_featureEvaluator, double& sum ) +inline int predictCategoricalStump( CascadeClassifierImpl& cascade, + Ptr &_featureEvaluator, double& sum ) { int nstages = (int)cascade.data.stages.size(); int nodeOfs = 0, leafOfs = 0; @@ -440,15 +570,15 @@ inline int predictCategoricalStump( CascadeClassifier& cascade, Ptr Date: Wed, 4 Dec 2013 21:56:35 +0400 Subject: [PATCH 47/97] trying to eliminate compile problems --- .../objdetect/doc/cascade_classification.rst | 38 -------------- .../objdetect/include/opencv2/objdetect.hpp | 51 ++++++++++--------- modules/objdetect/src/cascadedetect.cpp | 17 +++++-- modules/objdetect/src/cascadedetect.hpp | 6 +-- 4 files changed, 43 insertions(+), 69 deletions(-) diff --git a/modules/objdetect/doc/cascade_classification.rst b/modules/objdetect/doc/cascade_classification.rst index ecd27c7935..c351dc7138 100644 --- a/modules/objdetect/doc/cascade_classification.rst +++ b/modules/objdetect/doc/cascade_classification.rst @@ -221,44 +221,6 @@ The function is parallelized with the TBB library. * (Python) A face detection example using cascade classifiers can be found at opencv_source_code/samples/python2/facedetect.py -CascadeClassifier::setImage -------------------------------- -Sets an image for detection. - -.. ocv:function:: bool CascadeClassifier::setImage( Ptr& feval, const Mat& image ) - -.. ocv:cfunction:: void cvSetImagesForHaarClassifierCascade( CvHaarClassifierCascade* cascade, const CvArr* sum, const CvArr* sqsum, const CvArr* tilted_sum, double scale ) - - :param cascade: Haar classifier cascade (OpenCV 1.x API only). See :ocv:func:`CascadeClassifier::detectMultiScale` for more information. - - :param feval: Pointer to the feature evaluator used for computing features. - - :param image: Matrix of the type ``CV_8UC1`` containing an image where the features are computed. - -The function is automatically called by :ocv:func:`CascadeClassifier::detectMultiScale` at every image scale. But if you want to test various locations manually using :ocv:func:`CascadeClassifier::runAt`, you need to call the function before, so that the integral images are computed. - -.. note:: in the old API you need to supply integral images (that can be obtained using :ocv:cfunc:`Integral`) instead of the original image. - - -CascadeClassifier::runAt ----------------------------- -Runs the detector at the specified point. - -.. ocv:function:: int CascadeClassifier::runAt( Ptr& feval, Point pt, double& weight ) - -.. ocv:cfunction:: int cvRunHaarClassifierCascade( const CvHaarClassifierCascade* cascade, CvPoint pt, int start_stage=0 ) - - :param cascade: Haar classifier cascade (OpenCV 1.x API only). See :ocv:func:`CascadeClassifier::detectMultiScale` for more information. - - :param feval: Feature evaluator used for computing features. - - :param pt: Upper left point of the window where the features are computed. Size of the window is equal to the size of training images. - -The function returns 1 if the cascade classifier detects an object in the given location. -Otherwise, it returns negated index of the stage at which the candidate has been rejected. - -Use :ocv:func:`CascadeClassifier::setImage` to set the image for the detector to work with. - groupRectangles ------------------- Groups the object candidate rectangles. diff --git a/modules/objdetect/include/opencv2/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect.hpp index 26419bc596..c587b26a37 100644 --- a/modules/objdetect/include/opencv2/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect.hpp @@ -193,30 +193,31 @@ public: virtual Ptr getMaskGenerator() = 0; }; -class CV_EXPORTS_W CascadeClassifier : public BaseCascadeClassifier +class CV_EXPORTS_W CascadeClassifier { public: CV_WRAP CascadeClassifier(); CV_WRAP explicit CascadeClassifier(const String& filename); - virtual ~CascadeClassifier(); - CV_WRAP virtual bool empty() const; - CV_WRAP virtual bool load( const String& filename ); - CV_WRAP virtual void detectMultiScale( InputArray image, - CV_OUT std::vector& objects, - double scaleFactor = 1.1, - int minNeighbors = 3, int flags = 0, - Size minSize = Size(), - Size maxSize = Size() ); + ~CascadeClassifier(); + CV_WRAP bool empty() const; + CV_WRAP bool load( const String& filename ); + CV_WRAP bool read( const FileNode& node ); + CV_WRAP void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + double scaleFactor = 1.1, + int minNeighbors = 3, int flags = 0, + Size minSize = Size(), + Size maxSize = Size() ); - CV_WRAP virtual void detectMultiScale( InputArray image, - CV_OUT std::vector& objects, - CV_OUT std::vector& numDetections, - double scaleFactor=1.1, - int minNeighbors=3, int flags=0, - Size minSize=Size(), - Size maxSize=Size() ); + CV_WRAP void detectMultiScale( InputArray image, + CV_OUT std::vector& objects, + CV_OUT std::vector& numDetections, + double scaleFactor=1.1, + int minNeighbors=3, int flags=0, + Size minSize=Size(), + Size maxSize=Size() ); - CV_WRAP virtual void detectMultiScale( InputArray image, + CV_WRAP void detectMultiScale( InputArray image, CV_OUT std::vector& objects, CV_OUT std::vector& rejectLevels, CV_OUT std::vector& levelWeights, @@ -226,18 +227,18 @@ public: Size maxSize = Size(), bool outputRejectLevels = false ); - CV_WRAP virtual bool isOldFormatCascade() const; - CV_WRAP virtual Size getOriginalWindowSize() const; - CV_WRAP virtual int getFeatureType() const; - virtual void* getOldCascade(); + CV_WRAP bool isOldFormatCascade() const; + CV_WRAP Size getOriginalWindowSize() const; + CV_WRAP int getFeatureType() const; + void* getOldCascade(); - virtual void setMaskGenerator(const Ptr& maskGenerator); - virtual Ptr getMaskGenerator(); + void setMaskGenerator(const Ptr& maskGenerator); + Ptr getMaskGenerator(); protected: Ptr cc; }; -CV_EXPORTS Ptr createFaceDetectionMaskGenerator(); +CV_EXPORTS Ptr createFaceDetectionMaskGenerator(); //////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector ////////////// diff --git a/modules/objdetect/src/cascadedetect.cpp b/modules/objdetect/src/cascadedetect.cpp index 10c1b17a3c..2922375607 100644 --- a/modules/objdetect/src/cascadedetect.cpp +++ b/modules/objdetect/src/cascadedetect.cpp @@ -918,12 +918,12 @@ Ptr CascadeClassifierImpl::getMaskGenerato return maskGenerator; } -Ptr createFaceDetectionMaskGenerator() +Ptr createFaceDetectionMaskGenerator() { #ifdef HAVE_TEGRA_OPTIMIZATION return tegra::getCascadeClassifierMaskGenerator(*this); #else - return Ptr(); + return Ptr(); #endif } @@ -1390,6 +1390,17 @@ bool CascadeClassifier::load( const String& filename ) return !empty(); } +bool CascadeClassifier::read(const FileNode &root) +{ + Ptr ccimpl; + bool ok = ccimpl->read_(root); + if( ok ) + cc = ccimpl.staticCast(); + else + cc.release(); + return ok; +} + void CascadeClassifier::detectMultiScale( InputArray image, CV_OUT std::vector& objects, double scaleFactor, @@ -1452,7 +1463,7 @@ void* CascadeClassifier::getOldCascade() return cc->getOldCascade(); } -void CascadeClassifier::setMaskGenerator(const Ptr& maskGenerator) +void CascadeClassifier::setMaskGenerator(const Ptr& maskGenerator) { CV_Assert(!empty()); cc->setMaskGenerator(maskGenerator); diff --git a/modules/objdetect/src/cascadedetect.hpp b/modules/objdetect/src/cascadedetect.hpp index 862a273dcf..2505ea0711 100644 --- a/modules/objdetect/src/cascadedetect.hpp +++ b/modules/objdetect/src/cascadedetect.hpp @@ -86,7 +86,7 @@ protected: class Data { public: - struct CV_EXPORTS DTreeNode + struct DTreeNode { int featureIdx; float threshold; // for ordered features only @@ -94,12 +94,12 @@ protected: int right; }; - struct CV_EXPORTS DTree + struct DTree { int nodeCount; }; - struct CV_EXPORTS Stage + struct Stage { int first; int ntrees; From 828b0b151b16f00f9b8962c0b23cb5bb1d5f7ecb Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Wed, 4 Dec 2013 22:22:36 +0400 Subject: [PATCH 48/97] another attempt to fix compile errors --- modules/objdetect/include/opencv2/objdetect.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/objdetect/include/opencv2/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect.hpp index c587b26a37..d7f5b1a4b0 100644 --- a/modules/objdetect/include/opencv2/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect.hpp @@ -197,7 +197,7 @@ class CV_EXPORTS_W CascadeClassifier { public: CV_WRAP CascadeClassifier(); - CV_WRAP explicit CascadeClassifier(const String& filename); + CV_WRAP CascadeClassifier(const String& filename); ~CascadeClassifier(); CV_WRAP bool empty() const; CV_WRAP bool load( const String& filename ); @@ -234,7 +234,7 @@ public: void setMaskGenerator(const Ptr& maskGenerator); Ptr getMaskGenerator(); -protected: + Ptr cc; }; From 2153453fd1f925ef029bc62e1c8f6116736d93e2 Mon Sep 17 00:00:00 2001 From: Josep Bosch Date: Wed, 4 Dec 2013 22:32:20 +0100 Subject: [PATCH 49/97] Fixed little issue with mouse callback refering to issue 3409. Was using round instead of floor. --- modules/highgui/src/window_gtk.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/highgui/src/window_gtk.cpp b/modules/highgui/src/window_gtk.cpp index 3ee3d0c480..46ac61bfb9 100644 --- a/modules/highgui/src/window_gtk.cpp +++ b/modules/highgui/src/window_gtk.cpp @@ -1558,9 +1558,9 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da // image origin is not necessarily at (0,0) int x0 = (widget->allocation.width - image_widget->scaled_image->cols)/2; int y0 = (widget->allocation.height - image_widget->scaled_image->rows)/2; - pt.x = cvRound( ((pt32f.x-x0)*image_widget->original_image->cols)/ + pt.x = cvFloor( ((pt32f.x-x0)*image_widget->original_image->cols)/ image_widget->scaled_image->cols ); - pt.y = cvRound( ((pt32f.y-y0)*image_widget->original_image->rows)/ + pt.y = cvFloor( ((pt32f.y-y0)*image_widget->original_image->rows)/ image_widget->scaled_image->rows ); } else{ From 6ce03b04842292ce507a49ed435d50b2e20c5f2c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Tue, 3 Dec 2013 10:49:51 +0800 Subject: [PATCH 50/97] Fixed some implicitly type conversions between vector and scalar data type. There are some mixed implicitly/explicitly type conversion between scalar and vector. Although the spec allows those conversion, I prefer to make them consistent and use explicitly all the cases. Signed-off-by: Zhigang Gong --- modules/ocl/src/opencl/imgproc_threshold.cl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ocl/src/opencl/imgproc_threshold.cl b/modules/ocl/src/opencl/imgproc_threshold.cl index 63e410297b..85631be368 100644 --- a/modules/ocl/src/opencl/imgproc_threshold.cl +++ b/modules/ocl/src/opencl/imgproc_threshold.cl @@ -74,11 +74,11 @@ __kernel void threshold(__global const T * restrict src, int src_offset, int src VT vthresh = (VT)(thresh); #ifdef THRESH_BINARY - VT vecValue = sdata > vthresh ? max_val : (VT)(0); + VT vecValue = sdata > vthresh ? (VT)max_val : (VT)(0); #elif defined THRESH_BINARY_INV - VT vecValue = sdata > vthresh ? (VT)(0) : max_val; + VT vecValue = sdata > vthresh ? (VT)(0) : (VT)max_val; #elif defined THRESH_TRUNC - VT vecValue = sdata > vthresh ? thresh : sdata; + VT vecValue = sdata > vthresh ? (VT)thresh : sdata; #elif defined THRESH_TOZERO VT vecValue = sdata > vthresh ? sdata : (VT)(0); #elif defined THRESH_TOZERO_INV From e38ba1999b9de2931739cd0e0bc5838f8c2039fb Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Fri, 22 Nov 2013 14:47:58 +0400 Subject: [PATCH 51/97] facedetect --- samples/ocl/facedetect.cpp | 139 ++++++++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 1 deletion(-) diff --git a/samples/ocl/facedetect.cpp b/samples/ocl/facedetect.cpp index 10c6c4f4d2..7e760dacc8 100644 --- a/samples/ocl/facedetect.cpp +++ b/samples/ocl/facedetect.cpp @@ -9,6 +9,118 @@ using namespace std; using namespace cv; #define LOOP_NUM 10 +///////////////////////////////////////detectfaces with multithreading//////////////////////////////////////////// +#define MAX_THREADS 8 + +#if defined _WIN32|| defined _WIN64 + #include + #include + HANDLE handleThreads[MAX_THREADS]; +#endif + +#if defined __linux__ || defined __APPLE__ + #include + #include +#endif + +using namespace cv; + +#if defined _WIN32|| defined _WIN64 + void detectFaces(void* str) +#elif defined __linux__ || defined __APPLE__ + void* detectFaces(void* str) +#endif +{ + std::string fileName = *(std::string*)str; + ocl::OclCascadeClassifier cascade; + cascade.load("cv/cascadeandhog/cascades/haarcascade_frontalface_alt.xml" );//path to haarcascade_frontalface_alt.xml + Mat img = imread(fileName, CV_LOAD_IMAGE_COLOR); + if (img.empty()) + { + std::cout << "cann't open file " + fileName < oclfaces; + cascade.detectMultiScale(d_img, oclfaces, 1.1, 3, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30), Size(0, 0)); + + for(int i = 0; irun(); + } + int idx; + std::string fileName; +protected: + Thread():thread(NULL){} +}; + +class Thread_Win : public Thread +{ +private: + friend class Thread; + Thread_Win(){} +public: + ~Thread_Win(){}; + void run() + { +#if defined _WIN32|| defined _WIN64 + handleThreads[idx] = (HANDLE)_beginthread(detectFaces, 0, (void*)&fileName); + WaitForMultipleObjects(MAX_THREADS, handleThreads, TRUE, INFINITE); +#endif + } +}; + +class Thread_Lin : public Thread +{ + private: + friend class Thread; + Thread_Lin(){} +public: + ~Thread_Lin(){}; + void run() + { +#if defined __linux__ || defined __APPLE__ + pthread_t thread; + pthread_create(&thread, NULL, detectFaces, (void*)&fileName); + pthread_join (thread, NULL); +#endif + } +}; + +Thread::Thread(int _idx, std::string _fileName) +{ +#if defined _WIN32|| defined _WIN64 + thread = new Thread_Win(); +#endif +#if defined __linux__ || defined __APPLE__ + thread = new Thread_Lin(); +#endif + thread->idx = _idx; + thread->fileName = _fileName; +} + +///////////////////////////simple-threading faces detecting/////////////////////////////// + const static Scalar colors[] = { CV_RGB(0,0,255), CV_RGB(0,128,255), CV_RGB(0,255,255), @@ -58,7 +170,7 @@ static void Draw(Mat& img, vector& faces, double scale); // Else if will return (total diff of each cpu and gpu rects covered pixels)/(total cpu rects covered pixels) double checkRectSimilarity(Size sz, vector& cpu_rst, vector& gpu_rst); -int main( int argc, const char** argv ) +int facedetect_one_thread(int argc, const char** argv ) { const char* keys = "{ h | help | false | print help message }" @@ -176,9 +288,34 @@ int main( int argc, const char** argv ) } cvDestroyWindow("result"); + std::cout<< "simple-threading sample was finished" < threads; + for(int i = 0; irun(); + } + for(int i = 0; i& faces, ocl::OclCascadeClassifier& cascade, double scale, bool calTime) From 0a1ff0d42de3b9b40d5c153a6795e04f9a9da469 Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Mon, 2 Dec 2013 11:15:46 +0400 Subject: [PATCH 52/97] multithreading facedetector --- samples/ocl/facedetect.cpp | 242 ++++++++++++++----------------------- 1 file changed, 89 insertions(+), 153 deletions(-) diff --git a/samples/ocl/facedetect.cpp b/samples/ocl/facedetect.cpp index 7e760dacc8..0f452b945f 100644 --- a/samples/ocl/facedetect.cpp +++ b/samples/ocl/facedetect.cpp @@ -5,121 +5,15 @@ #include #include +#if defined(_MSC_VER) && (_MSC_VER >= 1700) + # include +#endif + using namespace std; using namespace cv; #define LOOP_NUM 10 -///////////////////////////////////////detectfaces with multithreading//////////////////////////////////////////// -#define MAX_THREADS 8 - -#if defined _WIN32|| defined _WIN64 - #include - #include - HANDLE handleThreads[MAX_THREADS]; -#endif - -#if defined __linux__ || defined __APPLE__ - #include - #include -#endif - -using namespace cv; - -#if defined _WIN32|| defined _WIN64 - void detectFaces(void* str) -#elif defined __linux__ || defined __APPLE__ - void* detectFaces(void* str) -#endif -{ - std::string fileName = *(std::string*)str; - ocl::OclCascadeClassifier cascade; - cascade.load("cv/cascadeandhog/cascades/haarcascade_frontalface_alt.xml" );//path to haarcascade_frontalface_alt.xml - Mat img = imread(fileName, CV_LOAD_IMAGE_COLOR); - if (img.empty()) - { - std::cout << "cann't open file " + fileName < oclfaces; - cascade.detectMultiScale(d_img, oclfaces, 1.1, 3, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30), Size(0, 0)); - - for(int i = 0; irun(); - } - int idx; - std::string fileName; -protected: - Thread():thread(NULL){} -}; - -class Thread_Win : public Thread -{ -private: - friend class Thread; - Thread_Win(){} -public: - ~Thread_Win(){}; - void run() - { -#if defined _WIN32|| defined _WIN64 - handleThreads[idx] = (HANDLE)_beginthread(detectFaces, 0, (void*)&fileName); - WaitForMultipleObjects(MAX_THREADS, handleThreads, TRUE, INFINITE); -#endif - } -}; - -class Thread_Lin : public Thread -{ - private: - friend class Thread; - Thread_Lin(){} -public: - ~Thread_Lin(){}; - void run() - { -#if defined __linux__ || defined __APPLE__ - pthread_t thread; - pthread_create(&thread, NULL, detectFaces, (void*)&fileName); - pthread_join (thread, NULL); -#endif - } -}; - -Thread::Thread(int _idx, std::string _fileName) -{ -#if defined _WIN32|| defined _WIN64 - thread = new Thread_Win(); -#endif -#if defined __linux__ || defined __APPLE__ - thread = new Thread_Lin(); -#endif - thread->idx = _idx; - thread->fileName = _fileName; -} - -///////////////////////////simple-threading faces detecting/////////////////////////////// +///////////////////////////single-threading faces detecting/////////////////////////////// const static Scalar colors[] = { CV_RGB(0,0,255), CV_RGB(0,128,255), @@ -134,7 +28,7 @@ const static Scalar colors[] = { CV_RGB(0,0,255), int64 work_begin = 0; int64 work_end = 0; -string outputName; +string inputName, outputName, cascadeName; static void workBegin() { @@ -170,35 +64,11 @@ static void Draw(Mat& img, vector& faces, double scale); // Else if will return (total diff of each cpu and gpu rects covered pixels)/(total cpu rects covered pixels) double checkRectSimilarity(Size sz, vector& cpu_rst, vector& gpu_rst); -int facedetect_one_thread(int argc, const char** argv ) +static int facedetect_one_thread(bool useCPU, double scale ) { - const char* keys = - "{ h | help | false | print help message }" - "{ i | input | | specify input image }" - "{ t | template | haarcascade_frontalface_alt.xml |" - " specify template file path }" - "{ c | scale | 1.0 | scale image }" - "{ s | use_cpu | false | use cpu or gpu to process the image }" - "{ o | output | facedetect_output.jpg |" - " specify output image save path(only works when input is images) }"; - - CommandLineParser cmd(argc, argv, keys); - if (cmd.get("help")) - { - cout << "Usage : facedetect [options]" << endl; - cout << "Available options:" << endl; - cmd.printParams(); - return EXIT_SUCCESS; - } - CvCapture* capture = 0; Mat frame, frameCopy, image; - bool useCPU = cmd.get("s"); - string inputName = cmd.get("i"); - outputName = cmd.get("o"); - string cascadeName = cmd.get("t"); - double scale = cmd.get("c"); ocl::OclCascadeClassifier cascade; CascadeClassifier cpu_cascade; @@ -288,32 +158,98 @@ int facedetect_one_thread(int argc, const char** argv ) } cvDestroyWindow("result"); - std::cout<< "simple-threading sample was finished" <= 1700) + +#define MAX_THREADS 10 + +static void detectFaces(std::string fileName) { - std::vector threads; - for(int i = 0; irun(); - } - for(int i = 0; i oclfaces; + cascade.detectMultiScale(d_img, oclfaces, 1.1, 3, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30), Size(0, 0)); + + for(unsigned int i = 0; i threads; + for(int i = 0; i= 1 }"; + + CommandLineParser cmd(argc, argv, keys); + if (cmd.get("help")) + { + cout << "Usage : facedetect [options]" << endl; + cout << "Available options:" << endl; + cmd.printParams(); + return EXIT_SUCCESS; + } + bool useCPU = cmd.get("s"); + inputName = cmd.get("i"); + outputName = cmd.get("o"); + cascadeName = cmd.get("t"); + double scale = cmd.get("c"); + int n = cmd.get("n"); + + if(n > 1) + { +#if defined(_MSC_VER) && (_MSC_VER >= 1700) + std::cout<<"multi-threaded sample is running" <& faces, From 3dcddad88aa13b729313939648c29f420a9f8054 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 5 Dec 2013 13:52:26 +0400 Subject: [PATCH 53/97] ocl: added workaround into Haar kernels --- modules/ocl/src/opencl/haarobjectdetect.cl | 86 ++++++++------- .../src/opencl/haarobjectdetect_scaled2.cl | 101 +++++++++--------- 2 files changed, 100 insertions(+), 87 deletions(-) diff --git a/modules/ocl/src/opencl/haarobjectdetect.cl b/modules/ocl/src/opencl/haarobjectdetect.cl index a62b3af8cb..980e85dd27 100644 --- a/modules/ocl/src/opencl/haarobjectdetect.cl +++ b/modules/ocl/src/opencl/haarobjectdetect.cl @@ -62,13 +62,13 @@ typedef struct __attribute__((aligned (128) )) GpuHidHaarTreeNode GpuHidHaarTreeNode; -typedef struct __attribute__((aligned (32))) GpuHidHaarClassifier -{ - int count __attribute__((aligned (4))); - GpuHidHaarTreeNode* node __attribute__((aligned (8))); - float* alpha __attribute__((aligned (8))); -} -GpuHidHaarClassifier; +//typedef struct __attribute__((aligned (32))) GpuHidHaarClassifier +//{ +// int count __attribute__((aligned (4))); +// GpuHidHaarTreeNode* node __attribute__((aligned (8))); +// float* alpha __attribute__((aligned (8))); +//} +//GpuHidHaarClassifier; typedef struct __attribute__((aligned (64))) GpuHidHaarStageClassifier @@ -84,22 +84,22 @@ typedef struct __attribute__((aligned (64))) GpuHidHaarStageClassifier GpuHidHaarStageClassifier; -typedef struct __attribute__((aligned (64))) GpuHidHaarClassifierCascade -{ - int count __attribute__((aligned (4))); - int is_stump_based __attribute__((aligned (4))); - int has_tilted_features __attribute__((aligned (4))); - int is_tree __attribute__((aligned (4))); - int pq0 __attribute__((aligned (4))); - int pq1 __attribute__((aligned (4))); - int pq2 __attribute__((aligned (4))); - int pq3 __attribute__((aligned (4))); - int p0 __attribute__((aligned (4))); - int p1 __attribute__((aligned (4))); - int p2 __attribute__((aligned (4))); - int p3 __attribute__((aligned (4))); - float inv_window_area __attribute__((aligned (4))); -} GpuHidHaarClassifierCascade; +//typedef struct __attribute__((aligned (64))) GpuHidHaarClassifierCascade +//{ +// int count __attribute__((aligned (4))); +// int is_stump_based __attribute__((aligned (4))); +// int has_tilted_features __attribute__((aligned (4))); +// int is_tree __attribute__((aligned (4))); +// int pq0 __attribute__((aligned (4))); +// int pq1 __attribute__((aligned (4))); +// int pq2 __attribute__((aligned (4))); +// int pq3 __attribute__((aligned (4))); +// int p0 __attribute__((aligned (4))); +// int p1 __attribute__((aligned (4))); +// int p2 __attribute__((aligned (4))); +// int p3 __attribute__((aligned (4))); +// float inv_window_area __attribute__((aligned (4))); +//} GpuHidHaarClassifierCascade; #ifdef PACKED_CLASSIFIER @@ -196,10 +196,12 @@ __kernel void gpuRunHaarClassifierCascadePacked( for(int stageloop = start_stage; (stageloop < end_stage) && result; stageloop++ ) {// iterate until candidate is exist float stage_sum = 0.0f; - int2 stageinfo = *(global int2*)(stagecascadeptr+stageloop); - float stagethreshold = as_float(stageinfo.y); + __global GpuHidHaarStageClassifier* stageinfo = (__global GpuHidHaarStageClassifier*) + ((__global uchar*)stagecascadeptr+stageloop*sizeof(GpuHidHaarStageClassifier)); + int stagecount = stageinfo->count; + float stagethreshold = stageinfo->threshold; int lcl_off = (lid_y*DATA_SIZE_X)+(lid_x); - for(int nodeloop = 0; nodeloop < stageinfo.x; nodecounter++,nodeloop++ ) + for(int nodeloop = 0; nodeloop < stagecount; nodecounter++,nodeloop++ ) { // simple macro to extract shorts from int #define M0(_t) ((_t)&0xFFFF) @@ -355,14 +357,17 @@ __kernel void __attribute__((reqd_work_group_size(8,8,1)))gpuRunHaarClassifierCa variance_norm_factor = variance_norm_factor * correction - mean * mean; variance_norm_factor = variance_norm_factor >=0.f ? sqrt(variance_norm_factor) : 1.f; - for(int stageloop = start_stage; (stageloop < split_stage) && result; stageloop++ ) + for(int stageloop = start_stage; (stageloop < split_stage) && result; stageloop++ ) { float stage_sum = 0.f; - int2 stageinfo = *(global int2*)(stagecascadeptr+stageloop); - float stagethreshold = as_float(stageinfo.y); - for(int nodeloop = 0; nodeloop < stageinfo.x; ) + __global GpuHidHaarStageClassifier* stageinfo = (__global GpuHidHaarStageClassifier*) + ((__global uchar*)stagecascadeptr+stageloop*sizeof(GpuHidHaarStageClassifier)); + int stagecount = stageinfo->count; + float stagethreshold = stageinfo->threshold; + for(int nodeloop = 0; nodeloop < stagecount; ) { - __global GpuHidHaarTreeNode* currentnodeptr = (nodeptr + nodecounter); + __global GpuHidHaarTreeNode* currentnodeptr = (__global GpuHidHaarTreeNode*) + (((__global uchar*)nodeptr) + nodecounter * sizeof(GpuHidHaarTreeNode)); int4 info1 = *(__global int4*)(&(currentnodeptr->p[0][0])); int4 info2 = *(__global int4*)(&(currentnodeptr->p[1][0])); @@ -418,7 +423,7 @@ __kernel void __attribute__((reqd_work_group_size(8,8,1)))gpuRunHaarClassifierCa #endif } - result = (stage_sum >= stagethreshold); + result = (stage_sum >= stagethreshold) ? 1 : 0; } if(factor < 2) { @@ -447,14 +452,17 @@ __kernel void __attribute__((reqd_work_group_size(8,8,1)))gpuRunHaarClassifierCa lclcount[0]=0; barrier(CLK_LOCAL_MEM_FENCE); - int2 stageinfo = *(global int2*)(stagecascadeptr+stageloop); - float stagethreshold = as_float(stageinfo.y); + //int2 stageinfo = *(global int2*)(stagecascadeptr+stageloop); + __global GpuHidHaarStageClassifier* stageinfo = (__global GpuHidHaarStageClassifier*) + ((__global uchar*)stagecascadeptr+stageloop*sizeof(GpuHidHaarStageClassifier)); + int stagecount = stageinfo->count; + float stagethreshold = stageinfo->threshold; int perfscale = queuecount > 4 ? 3 : 2; int queuecount_loop = (queuecount + (1<> perfscale; int lcl_compute_win = lcl_sz >> perfscale; int lcl_compute_win_id = (lcl_id >>(6-perfscale)); - int lcl_loops = (stageinfo.x + lcl_compute_win -1) >> (6-perfscale); + int lcl_loops = (stagecount + lcl_compute_win -1) >> (6-perfscale); int lcl_compute_id = lcl_id - (lcl_compute_win_id << (6-perfscale)); for(int queueloop=0; queueloopp[0][0])); int4 info2 = *(__global int4*)(&(currentnodeptr->p[1][0])); @@ -549,7 +557,7 @@ __kernel void __attribute__((reqd_work_group_size(8,8,1)))gpuRunHaarClassifierCa queuecount = lclcount[0]; barrier(CLK_LOCAL_MEM_FENCE); - nodecounter += stageinfo.x; + nodecounter += stagecount; }//end for(int stageloop = splitstage; stageloop< endstage && queuecount>0;stageloop++) if(lcl_id> 16; int totalgrp = scaleinfo1.y & 0xffff; float factor = as_float(scaleinfo1.w); @@ -174,15 +173,18 @@ __kernel void gpuRunHaarClassifierCascade_scaled2( for (int stageloop = start_stage; (stageloop < end_stage) && result; stageloop++) { float stage_sum = 0.f; - int stagecount = stagecascadeptr[stageloop].count; + __global GpuHidHaarStageClassifier* stageinfo = (__global GpuHidHaarStageClassifier*) + (((__global uchar*)stagecascadeptr_)+stageloop*sizeof(GpuHidHaarStageClassifier)); + int stagecount = stageinfo->count; for (int nodeloop = 0; nodeloop < stagecount;) { - __global GpuHidHaarTreeNode *currentnodeptr = (nodeptr + nodecounter); + __global GpuHidHaarTreeNode* currentnodeptr = (__global GpuHidHaarTreeNode*) + (((__global uchar*)nodeptr_) + nodecounter * sizeof(GpuHidHaarTreeNode)); int4 info1 = *(__global int4 *)(&(currentnodeptr->p[0][0])); int4 info2 = *(__global int4 *)(&(currentnodeptr->p[1][0])); int4 info3 = *(__global int4 *)(&(currentnodeptr->p[2][0])); float4 w = *(__global float4 *)(&(currentnodeptr->weight[0])); - float3 alpha3 = *(__global float3 *)(&(currentnodeptr->alpha[0])); + float3 alpha3 = *(__global float3*)(&(currentnodeptr->alpha[0])); float nodethreshold = w.w * variance_norm_factor; info1.x += p_offset; @@ -204,7 +206,7 @@ __kernel void gpuRunHaarClassifierCascade_scaled2( sum[clamp(mad24(info3.w, step, info3.x), 0, max_idx)] + sum[clamp(mad24(info3.w, step, info3.z), 0, max_idx)]) * w.z; - bool passThres = classsum >= nodethreshold; + bool passThres = (classsum >= nodethreshold) ? 1 : 0; #if STUMP_BASED stage_sum += passThres ? alpha3.y : alpha3.x; @@ -234,7 +236,8 @@ __kernel void gpuRunHaarClassifierCascade_scaled2( } #endif } - result = (int)(stage_sum >= stagecascadeptr[stageloop].threshold); + + result = (stage_sum >= stageinfo->threshold) ? 1 : 0; } barrier(CLK_LOCAL_MEM_FENCE); @@ -281,11 +284,14 @@ __kernel void gpuRunHaarClassifierCascade_scaled2( } } } -__kernel void gpuscaleclassifier(global GpuHidHaarTreeNode *orinode, global GpuHidHaarTreeNode *newnode, float scale, float weight_scale, int nodenum) +__kernel void gpuscaleclassifier(global GpuHidHaarTreeNode *orinode, global GpuHidHaarTreeNode *newnode, float scale, float weight_scale, const int nodenum) { - int counter = get_global_id(0); + const int counter = get_global_id(0); int tr_x[3], tr_y[3], tr_h[3], tr_w[3], i = 0; - GpuHidHaarTreeNode t1 = *(orinode + counter); + GpuHidHaarTreeNode t1 = *(__global GpuHidHaarTreeNode*) + (((__global uchar*)orinode) + counter * sizeof(GpuHidHaarTreeNode)); + __global GpuHidHaarTreeNode* pNew = (__global GpuHidHaarTreeNode*) + (((__global uchar*)newnode) + (counter + nodenum) * sizeof(GpuHidHaarTreeNode)); #pragma unroll for (i = 0; i < 3; i++) @@ -297,22 +303,21 @@ __kernel void gpuscaleclassifier(global GpuHidHaarTreeNode *orinode, global GpuH } t1.weight[0] = -(t1.weight[1] * tr_h[1] * tr_w[1] + t1.weight[2] * tr_h[2] * tr_w[2]) / (tr_h[0] * tr_w[0]); - counter += nodenum; #pragma unroll for (i = 0; i < 3; i++) { - newnode[counter].p[i][0] = tr_x[i]; - newnode[counter].p[i][1] = tr_y[i]; - newnode[counter].p[i][2] = tr_x[i] + tr_w[i]; - newnode[counter].p[i][3] = tr_y[i] + tr_h[i]; - newnode[counter].weight[i] = t1.weight[i] * weight_scale; + pNew->p[i][0] = tr_x[i]; + pNew->p[i][1] = tr_y[i]; + pNew->p[i][2] = tr_x[i] + tr_w[i]; + pNew->p[i][3] = tr_y[i] + tr_h[i]; + pNew->weight[i] = t1.weight[i] * weight_scale; } - newnode[counter].left = t1.left; - newnode[counter].right = t1.right; - newnode[counter].threshold = t1.threshold; - newnode[counter].alpha[0] = t1.alpha[0]; - newnode[counter].alpha[1] = t1.alpha[1]; - newnode[counter].alpha[2] = t1.alpha[2]; + pNew->left = t1.left; + pNew->right = t1.right; + pNew->threshold = t1.threshold; + pNew->alpha[0] = t1.alpha[0]; + pNew->alpha[1] = t1.alpha[1]; + pNew->alpha[2] = t1.alpha[2]; } From b93002872750b8f8844fee69180aaad57d328e85 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Thu, 5 Dec 2013 14:36:45 +0400 Subject: [PATCH 54/97] Added cv::flip using Transparent API --- modules/core/src/copy.cpp | 54 +++++++++++++- modules/core/src/opencl/flip.cl | 102 ++++++++++++++++++++++++++ modules/core/test/ocl/test_arithm.cpp | 41 +++++++++++ 3 files changed, 194 insertions(+), 3 deletions(-) create mode 100644 modules/core/src/opencl/flip.cl diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index ee34ef4516..8e60227a54 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -6,7 +6,6 @@ // If you do not agree to this license, do not download, install, // copy or use the software. // -// // License Agreement // For Open Source Computer Vision Library // @@ -47,6 +46,7 @@ // */ #include "precomp.hpp" +#include "opencl_kernels.hpp" namespace cv { @@ -477,11 +477,59 @@ flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, } } +enum { FLIP_COLS = 1 << 0, FLIP_ROWS = 1 << 1, FLIP_BOTH = FLIP_ROWS | FLIP_COLS }; + +static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode ) +{ + int type = _src.type(), cn = CV_MAT_CN(type); + + if (cn > 4 || cn == 3) + return false; + + const char * kernelName; + int flipType; + + if (flipCode == 0) + kernelName = "arithm_flip_rows", flipType = FLIP_ROWS; + else if (flipCode > 0) + kernelName = "arithm_flip_cols", flipType = FLIP_COLS; + else + kernelName = "arithm_flip_rows_cols", flipType = FLIP_BOTH; + + Size size = _src.size(); + int cols = size.width, rows = size.height; + if ((cols == 1 && flipType == FLIP_COLS) || + (rows == 1 && flipType == FLIP_ROWS) || + (rows == 1 && cols == 1 && flipType == FLIP_BOTH)) + { + _src.copyTo(_dst); + return true; + } + + ocl::Kernel k(kernelName, ocl::core::flip_oclsrc, + format( "-D type=%s", ocl::memopTypeToStr(type))); + if (k.empty()) + return false; + + _dst.create(size, type); + UMat src = _src.getUMat(), dst = _dst.getUMat(); + + cols = flipType == FLIP_COLS ? ((cols+1)/2) : cols; + rows = flipType & FLIP_ROWS ? ((rows+1)/2) : rows; + + size_t globalsize[2] = { cols, rows }; + return k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), rows, cols).run(2, globalsize, NULL, false); +} + void flip( InputArray _src, OutputArray _dst, int flip_mode ) { - Mat src = _src.getMat(); + CV_Assert( _src.dims() <= 2 ); - CV_Assert( src.dims <= 2 ); + bool use_opencl = ocl::useOpenCL() && _dst.isUMat(); + if ( use_opencl && ocl_flip(_src,_dst, flip_mode)) + return; + + Mat src = _src.getMat(); _dst.create( src.size(), src.type() ); Mat dst = _dst.getMat(); size_t esz = src.elemSize(); diff --git a/modules/core/src/opencl/flip.cl b/modules/core/src/opencl/flip.cl new file mode 100644 index 0000000000..4e53041539 --- /dev/null +++ b/modules/core/src/opencl/flip.cl @@ -0,0 +1,102 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do 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, 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 OpenCV Foundation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#define sizeoftype ((int)sizeof(type)) + +__kernel void arithm_flip_rows(__global const uchar* srcptr, int srcstep, int srcoffset, + __global uchar* dstptr, int dststep, int dstoffset, + int rows, int cols, int thread_rows, int thread_cols) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if (x < cols && y < thread_rows) + { + __global const type* src0 = (__global const type*)(srcptr + mad24(y, srcstep, srcoffset + x * sizeoftype)); + __global const type* src1 = (__global const type*)(srcptr + mad24(rows - y - 1, srcstep, srcoffset + x * sizeoftype)); + + __global type* dst0 = (__global type*)(dstptr + mad24(y, dststep, dstoffset + x * sizeoftype)); + __global type* dst1 = (__global type*)(dstptr + mad24(rows - y - 1, dststep, dstoffset + x * sizeoftype)); + + dst0[0] = src1[0]; + dst1[0] = src0[0]; + } +} + +__kernel void arithm_flip_rows_cols(__global const uchar* srcptr, int srcstep, int srcoffset, + __global uchar* dstptr, int dststep, int dstoffset, + int rows, int cols, int thread_rows, int thread_cols) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if (x < cols && y < thread_rows) + { + __global const type* src0 = (__global const type*)(srcptr + mad24(y, srcstep, x*sizeoftype + srcoffset)); + __global const type* src1 = (__global const type*)(srcptr + mad24(rows - y - 1, srcstep, (cols - x - 1)*sizeoftype + srcoffset)); + + __global type* dst0 = (__global type*)(dstptr + mad24(rows - y - 1, dststep, (cols - x - 1)*sizeoftype + dstoffset)); + __global type* dst1 = (__global type*)(dstptr + mad24(y, dststep, x * sizeoftype + dstoffset)); + + dst0[0] = src0[0]; + dst1[0] = src1[0]; + } +} + +__kernel void arithm_flip_cols(__global const uchar* srcptr, int srcstep, int srcoffset, + __global uchar* dstptr, int dststep, int dstoffset, + int rows, int cols, int thread_rows, int thread_cols) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if (x < thread_cols && y < rows) + { + __global const type* src0 = (__global const type*)(srcptr + mad24(y, srcstep, x * sizeoftype + srcoffset)); + __global const type* src1 = (__global const type*)(srcptr + mad24(y, srcstep, (cols - x - 1)*sizeoftype + srcoffset)); + + __global type* dst0 = (__global type*)(dstptr + mad24(y, dststep, (cols - x - 1)*sizeoftype + dstoffset)); + __global type* dst1 = (__global type*)(dstptr + mad24(y, dststep, x * sizeoftype + dstoffset)); + + dst1[0] = src1[0]; + dst0[0] = src0[0]; + } +} diff --git a/modules/core/test/ocl/test_arithm.cpp b/modules/core/test/ocl/test_arithm.cpp index 10cec7bc00..4755e69c24 100644 --- a/modules/core/test/ocl/test_arithm.cpp +++ b/modules/core/test/ocl/test_arithm.cpp @@ -964,6 +964,46 @@ OCL_TEST_P(Magnitude, Mat) } } +//////////////////////////////// Flip ///////////////////////////////////////////////// + +typedef ArithmTestBase Flip; + +OCL_TEST_P(Flip, X) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::flip(src1_roi, dst1_roi, 0)); + OCL_ON(cv::flip(usrc1_roi, udst1_roi, 0)); + Near(1e-5); + } +} + +OCL_TEST_P(Flip, Y) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::flip(src1_roi, dst1_roi, 1)); + OCL_ON(cv::flip(usrc1_roi, udst1_roi, 1)); + Near(1e-5); + } +} + +OCL_TEST_P(Flip, BOTH) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(cv::flip(src1_roi, dst1_roi, -1)); + OCL_ON(cv::flip(usrc1_roi, udst1_roi, -1)); + Near(1e-5); + } +} + //////////////////////////////////////// Instantiation ///////////////////////////////////////// OCL_INSTANTIATE_TEST_CASE_P(Arithm, Lut, Combine(::testing::Values(CV_8U, CV_8S), OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool(), Bool())); @@ -993,6 +1033,7 @@ OCL_INSTANTIATE_TEST_CASE_P(Arithm, Log, Combine(::testing::Values(CV_32F, CV_64 OCL_INSTANTIATE_TEST_CASE_P(Arithm, Exp, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Arithm, Phase, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Arithm, Magnitude, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Arithm, Flip, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); } } // namespace cvtest::ocl From 3bc952ed34b8f198da7c679f03a51c27f984fb76 Mon Sep 17 00:00:00 2001 From: Peter Andreas Entschev Date: Thu, 5 Dec 2013 19:27:10 -0200 Subject: [PATCH 55/97] ocl::BruteForceMatcher fix wrong use of oclMat::ptr(). The oclMat::ptr() method was mistakenly used in ocl::BruteForceMatcher to pass a pointer to a oclMat object. The ptr() method returns a uchar pointer to the cl_mem data structure and this method will be removed. --- modules/ocl/src/brute_force_matcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ocl/src/brute_force_matcher.cpp b/modules/ocl/src/brute_force_matcher.cpp index b1efe8ca64..b51d4f194c 100644 --- a/modules/ocl/src/brute_force_matcher.cpp +++ b/modules/ocl/src/brute_force_matcher.cpp @@ -677,7 +677,7 @@ void cv::ocl::BruteForceMatcher_OCL_base::matchCollection(const oclMat &query, c ensureSizeIsEnough(1, nQuery, CV_32S, imgIdx); ensureSizeIsEnough(1, nQuery, CV_32F, distance); - matchDispatcher(query, (const oclMat *)trainCollection.ptr(), trainCollection.cols, masks, trainIdx, imgIdx, distance, distType); + matchDispatcher(query, &trainCollection, trainCollection.cols, masks, trainIdx, imgIdx, distance, distType); return; } From 7a78559708776b28d33c2ff8a5d46a0699f748f2 Mon Sep 17 00:00:00 2001 From: Konstantin Matskevich Date: Fri, 6 Dec 2013 12:12:24 +0400 Subject: [PATCH 56/97] some fixes --- samples/ocl/facedetect.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/samples/ocl/facedetect.cpp b/samples/ocl/facedetect.cpp index 0f452b945f..78a0775151 100644 --- a/samples/ocl/facedetect.cpp +++ b/samples/ocl/facedetect.cpp @@ -74,7 +74,7 @@ static int facedetect_one_thread(bool useCPU, double scale ) if( !cascade.load( cascadeName ) || !cpu_cascade.load(cascadeName) ) { - cout << "ERROR: Could not load classifier cascade" << endl; + cout << "ERROR: Could not load classifier cascade: " << cascadeName << endl; return EXIT_FAILURE; } @@ -170,7 +170,12 @@ static int facedetect_one_thread(bool useCPU, double scale ) static void detectFaces(std::string fileName) { ocl::OclCascadeClassifier cascade; - cascade.load(cascadeName); + if(!cascade.load(cascadeName)) + { + std::cout << "ERROR: Could not load classifier cascade: " << cascadeName << std::endl; + return; + } + Mat img = imread(fileName, CV_LOAD_IMAGE_COLOR); if (img.empty()) { @@ -187,8 +192,16 @@ static void detectFaces(std::string fileName) for(unsigned int i = 0; i 0 && outputName[n-1] != '.') + n--; + if( n == 0 ) + { + std::cout << "Invalid output file name: " << outputName << std::endl; + return; + } + imwrite(outputName.substr(0,n-1) + "_" + std::to_string(_threadid) + outputName.substr(n-1, outputName.length()-1), img); } static void facedetect_multithreading(int nthreads) From 3eaa8f149b18f422e606f7411a388bb1fd9e7e5e Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 5 Dec 2013 19:43:50 +0400 Subject: [PATCH 57/97] added cv::intergal to T-API --- modules/core/include/opencv2/core/mat.hpp | 2 + modules/core/src/matrix.cpp | 79 +++ .../doc/miscellaneous_transformations.rst | 10 +- modules/imgproc/include/opencv2/imgproc.hpp | 4 +- modules/imgproc/src/opencl/integral_sqrsum.cl | 512 ++++++++++++++++++ modules/imgproc/src/opencl/integral_sum.cl | 413 ++++++++++++++ modules/imgproc/src/sumpixels.cpp | 191 +++++-- modules/imgproc/test/ocl/test_imgproc.cpp | 61 ++- .../org/opencv/test/imgproc/ImgprocTest.java | 4 +- 9 files changed, 1218 insertions(+), 58 deletions(-) create mode 100644 modules/imgproc/src/opencl/integral_sqrsum.cl create mode 100644 modules/imgproc/src/opencl/integral_sum.cl diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index f864510de6..401467534b 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -129,6 +129,8 @@ public: virtual bool isContinuous(int i=-1) const; virtual bool empty() const; virtual void copyTo(const _OutputArray& arr) const; + virtual size_t offset(int i=-1) const; + virtual size_t step(int i=-1) const; bool isMat() const; bool isUMat() const; bool isMatVectot() const; diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 4e9be9807c..72c6c4756d 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -1792,6 +1792,85 @@ bool _InputArray::isContinuous(int i) const return false; } +size_t _InputArray::offset(int i) const +{ + int k = kind(); + + if( k == MAT ) + { + CV_Assert( i < 0 ); + const Mat * const m = ((const Mat*)obj); + return (size_t)(m->data - m->datastart); + } + + if( k == UMAT ) + { + CV_Assert( i < 0 ); + return ((const UMat*)obj)->offset; + } + + if( k == EXPR || k == MATX || k == STD_VECTOR || k == NONE || k == STD_VECTOR_VECTOR) + return 0; + + if( k == STD_VECTOR_MAT ) + { + const std::vector& vv = *(const std::vector*)obj; + if( i < 0 ) + return 1; + CV_Assert( i < (int)vv.size() ); + + return (size_t)(vv[i].data - vv[i].datastart); + } + + if( k == GPU_MAT ) + { + CV_Assert( i < 0 ); + const cuda::GpuMat * const m = ((const cuda::GpuMat*)obj); + return (size_t)(m->data - m->datastart); + } + + CV_Error(Error::StsNotImplemented, ""); + return 0; +} + +size_t _InputArray::step(int i) const +{ + int k = kind(); + + if( k == MAT ) + { + CV_Assert( i < 0 ); + return ((const Mat*)obj)->step; + } + + if( k == UMAT ) + { + CV_Assert( i < 0 ); + return ((const UMat*)obj)->step; + } + + if( k == EXPR || k == MATX || k == STD_VECTOR || k == NONE || k == STD_VECTOR_VECTOR) + return 0; + + if( k == STD_VECTOR_MAT ) + { + const std::vector& vv = *(const std::vector*)obj; + if( i < 0 ) + return 1; + CV_Assert( i < (int)vv.size() ); + return vv[i].step; + } + + if( k == GPU_MAT ) + { + CV_Assert( i < 0 ); + return ((const cuda::GpuMat*)obj)->step; + } + + CV_Error(Error::StsNotImplemented, ""); + return 0; +} + void _InputArray::copyTo(const _OutputArray& arr) const { int k = kind(); diff --git a/modules/imgproc/doc/miscellaneous_transformations.rst b/modules/imgproc/doc/miscellaneous_transformations.rst index 47de0b442d..df63c929b5 100644 --- a/modules/imgproc/doc/miscellaneous_transformations.rst +++ b/modules/imgproc/doc/miscellaneous_transformations.rst @@ -596,15 +596,15 @@ Calculates the integral of an image. .. ocv:function:: void integral( InputArray src, OutputArray sum, int sdepth=-1 ) -.. ocv:function:: void integral( InputArray src, OutputArray sum, OutputArray sqsum, int sdepth=-1 ) +.. ocv:function:: void integral( InputArray src, OutputArray sum, OutputArray sqsum, int sdepth=-1, int sqdepth=-1 ) -.. ocv:function:: void integral( InputArray src, OutputArray sum, OutputArray sqsum, OutputArray tilted, int sdepth=-1 ) +.. ocv:function:: void integral( InputArray src, OutputArray sum, OutputArray sqsum, OutputArray tilted, int sdepth=-1, int sqdepth=-1 ) .. ocv:pyfunction:: cv2.integral(src[, sum[, sdepth]]) -> sum -.. ocv:pyfunction:: cv2.integral2(src[, sum[, sqsum[, sdepth]]]) -> sum, sqsum +.. ocv:pyfunction:: cv2.integral2(src[, sum[, sqsum[, sdepth[, sqdepth]]]]) -> sum, sqsum -.. ocv:pyfunction:: cv2.integral3(src[, sum[, sqsum[, tilted[, sdepth]]]]) -> sum, sqsum, tilted +.. ocv:pyfunction:: cv2.integral3(src[, sum[, sqsum[, tilted[, sdepth[, sqdepth]]]]]) -> sum, sqsum, tilted .. ocv:cfunction:: void cvIntegral( const CvArr* image, CvArr* sum, CvArr* sqsum=NULL, CvArr* tilted_sum=NULL ) @@ -618,6 +618,8 @@ Calculates the integral of an image. :param sdepth: desired depth of the integral and the tilted integral images, ``CV_32S``, ``CV_32F``, or ``CV_64F``. + :param sqdepth: desired depth of the integral image of squared pixel values, ``CV_32F`` or ``CV_64F``. + The functions calculate one or more integral images for the source image as follows: .. math:: diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 25f9797299..59f6ae01a9 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -1241,12 +1241,12 @@ CV_EXPORTS_W void integral( InputArray src, OutputArray sum, int sdepth = -1 ); //! computes the integral image and integral for the squared image CV_EXPORTS_AS(integral2) void integral( InputArray src, OutputArray sum, - OutputArray sqsum, int sdepth = -1 ); + OutputArray sqsum, int sdepth = -1, int sqdepth = -1 ); //! computes the integral image, integral for the squared image and the tilted integral image CV_EXPORTS_AS(integral3) void integral( InputArray src, OutputArray sum, OutputArray sqsum, OutputArray tilted, - int sdepth = -1 ); + int sdepth = -1, int sqdepth = -1 ); //! adds image to the accumulator (dst += src). Unlike cv::add, dst and src can have different types. CV_EXPORTS_W void accumulate( InputArray src, InputOutputArray dst, diff --git a/modules/imgproc/src/opencl/integral_sqrsum.cl b/modules/imgproc/src/opencl/integral_sqrsum.cl new file mode 100644 index 0000000000..8b5d2452b8 --- /dev/null +++ b/modules/imgproc/src/opencl/integral_sqrsum.cl @@ -0,0 +1,512 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do 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-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Shengen Yan,yanshengen@gmail.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 materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors as is and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including 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 DOUBLE_SUPPORT +#ifdef cl_amd_fp64 +#pragma OPENCL EXTENSION cl_amd_fp64:enable +#elif defined (cl_khr_fp64) +#pragma OPENCL EXTENSION cl_khr_fp64:enable +#endif +#endif + +#if sqdepth == 6 +#define CONVERT(step) ((step)>>1) +#else +#define CONVERT(step) ((step)) +#endif + +#define LSIZE 256 +#define LSIZE_1 255 +#define LSIZE_2 254 +#define HF_LSIZE 128 +#define LOG_LSIZE 8 +#define LOG_NUM_BANKS 5 +#define NUM_BANKS 32 +#define GET_CONFLICT_OFFSET(lid) ((lid) >> LOG_NUM_BANKS) + +#define noconvert + +#if sdepth == 4 + +kernel void integral_cols(__global uchar4 *src, __global int *sum, __global TYPE *sqsum, + int src_offset, int pre_invalid, int rows, int cols, int src_step, int dst_step, int dst1_step) +{ + int lid = get_local_id(0); + int gid = get_group_id(0); + int4 src_t[2], sum_t[2]; + TYPE4 sqsum_t[2]; + __local int4 lm_sum[2][LSIZE + LOG_LSIZE]; + __local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE]; + __local int* sum_p; + __local TYPE* sqsum_p; + src_step = src_step >> 2; + gid = gid << 1; + for(int i = 0; i < rows; i =i + LSIZE_1) + { + src_t[0] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + min(gid, cols - 1)]) : 0); + src_t[1] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + min(gid + 1, cols - 1)]) : 0); + + sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); + sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]); + sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); + sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]); + barrier(CLK_LOCAL_MEM_FENCE); + + int bf_loc = lid + GET_CONFLICT_OFFSET(lid); + lm_sum[0][bf_loc] = src_t[0]; + lm_sqsum[0][bf_loc] = convert_TYPE4(src_t[0] * src_t[0]); + + lm_sum[1][bf_loc] = src_t[1]; + lm_sqsum[1][bf_loc] = convert_TYPE4(src_t[1] * src_t[1]); + + int offset = 1; + for(int d = LSIZE >> 1 ; d > 0; d>>=1) + { + barrier(CLK_LOCAL_MEM_FENCE); + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; + } + offset <<= 1; + } + barrier(CLK_LOCAL_MEM_FENCE); + if(lid < 2) + { + lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; + lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0; + } + for(int d = 1; d < LSIZE; d <<= 1) + { + barrier(CLK_LOCAL_MEM_FENCE); + offset >>= 1; + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; + + lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; + lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step /4, loc_s1 = loc_s0 + dst_step ; + int loc_sq0 = gid * CONVERT(dst1_step) + i + lid - 1 - pre_invalid * dst1_step / sizeof(TYPE),loc_sq1 = loc_sq0 + CONVERT(dst1_step); + if(lid > 0 && (i+lid) <= rows) + { + lm_sum[0][bf_loc] += sum_t[0]; + lm_sum[1][bf_loc] += sum_t[1]; + lm_sqsum[0][bf_loc] += sqsum_t[0]; + lm_sqsum[1][bf_loc] += sqsum_t[1]; + sum_p = (__local int*)(&(lm_sum[0][bf_loc])); + sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue; + sum[loc_s0 + k * dst_step / 4] = sum_p[k]; + sqsum[loc_sq0 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k]; + } + sum_p = (__local int*)(&(lm_sum[1][bf_loc])); + sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 4 + k + 4 >= cols + pre_invalid) break; + sum[loc_s1 + k * dst_step / 4] = sum_p[k]; + sqsum[loc_sq1 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} + +kernel void integral_rows(__global int4 *srcsum, __global TYPE4 * srcsqsum,__global int *sum, + __global TYPE *sqsum, int rows, int cols, int src_step, int src1_step, int sum_step, + int sqsum_step, int sum_offset, int sqsum_offset) +{ + int lid = get_local_id(0); + int gid = get_group_id(0); + int4 src_t[2], sum_t[2]; + TYPE4 sqsrc_t[2],sqsum_t[2]; + __local int4 lm_sum[2][LSIZE + LOG_LSIZE]; + __local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE]; + __local int *sum_p; + __local TYPE *sqsum_p; + src_step = src_step >> 4; + src1_step = (src1_step / sizeof(TYPE)) >> 2 ; + gid <<= 1; + for(int i = 0; i < rows; i =i + LSIZE_1) + { + src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid ] : (int4)0; + sqsrc_t[0] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid ] : (TYPE4)0; + src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid + 1] : (int4)0; + sqsrc_t[1] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid + 1] : (TYPE4)0; + + sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); + sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]); + sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); + sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]); + barrier(CLK_LOCAL_MEM_FENCE); + + int bf_loc = lid + GET_CONFLICT_OFFSET(lid); + lm_sum[0][bf_loc] = src_t[0]; + lm_sqsum[0][bf_loc] = sqsrc_t[0]; + + lm_sum[1][bf_loc] = src_t[1]; + lm_sqsum[1][bf_loc] = sqsrc_t[1]; + + int offset = 1; + for(int d = LSIZE >> 1 ; d > 0; d>>=1) + { + barrier(CLK_LOCAL_MEM_FENCE); + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; + } + offset <<= 1; + } + barrier(CLK_LOCAL_MEM_FENCE); + if(lid < 2) + { + lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; + lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0; + } + for(int d = 1; d < LSIZE; d <<= 1) + { + barrier(CLK_LOCAL_MEM_FENCE); + offset >>= 1; + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; + + lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; + lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + if(gid == 0 && (i + lid) <= rows) + { + sum[sum_offset + i + lid] = 0; + sqsum[sqsum_offset + i + lid] = 0; + } + if(i + lid == 0) + { + int loc0 = gid * sum_step; + int loc1 = gid * CONVERT(sqsum_step); + for(int k = 1; k <= 8; k++) + { + if(gid * 4 + k > cols) break; + sum[sum_offset + loc0 + k * sum_step / 4] = 0; + sqsum[sqsum_offset + loc1 + k * sqsum_step / sizeof(TYPE)] = 0; + } + } + int loc_s0 = sum_offset + gid * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ; + int loc_sq0 = sqsum_offset + gid * CONVERT(sqsum_step) + sqsum_step / sizeof(TYPE) + i + lid, loc_sq1 = loc_sq0 + CONVERT(sqsum_step) ; + + if(lid > 0 && (i+lid) <= rows) + { + lm_sum[0][bf_loc] += sum_t[0]; + lm_sum[1][bf_loc] += sum_t[1]; + lm_sqsum[0][bf_loc] += sqsum_t[0]; + lm_sqsum[1][bf_loc] += sqsum_t[1]; + sum_p = (__local int*)(&(lm_sum[0][bf_loc])); + sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 4 + k >= cols) break; + sum[loc_s0 + k * sum_step / 4] = sum_p[k]; + sqsum[loc_sq0 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k]; + } + sum_p = (__local int*)(&(lm_sum[1][bf_loc])); + sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 4 + 4 + k >= cols) break; + sum[loc_s1 + k * sum_step / 4] = sum_p[k]; + sqsum[loc_sq1 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} + +#elif sdepth == 5 + +kernel void integral_cols(__global uchar4 *src, __global float *sum, __global TYPE *sqsum, + int src_offset, int pre_invalid, int rows, int cols, int src_step, int dst_step, int dst1_step) +{ + int lid = get_local_id(0); + int gid = get_group_id(0); + float4 src_t[2], sum_t[2]; + TYPE4 sqsum_t[2]; + __local float4 lm_sum[2][LSIZE + LOG_LSIZE]; + __local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE]; + __local float* sum_p; + __local TYPE* sqsum_p; + src_step = src_step >> 2; + gid = gid << 1; + for(int i = 0; i < rows; i =i + LSIZE_1) + { + src_t[0] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + min(gid, cols - 1)]) : (float4)0); + src_t[1] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + min(gid + 1, cols - 1)]) : (float4)0); + + sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); + sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]); + sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); + sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]); + barrier(CLK_LOCAL_MEM_FENCE); + + int bf_loc = lid + GET_CONFLICT_OFFSET(lid); + lm_sum[0][bf_loc] = src_t[0]; + lm_sqsum[0][bf_loc] = convert_TYPE4(src_t[0] * src_t[0]); +// printf("%f\n", src_t[0].s0); + + lm_sum[1][bf_loc] = src_t[1]; + lm_sqsum[1][bf_loc] = convert_TYPE4(src_t[1] * src_t[1]); + + int offset = 1; + for(int d = LSIZE >> 1 ; d > 0; d>>=1) + { + barrier(CLK_LOCAL_MEM_FENCE); + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; + } + offset <<= 1; + } + barrier(CLK_LOCAL_MEM_FENCE); + if(lid < 2) + { + lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; + lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0; + } + for(int d = 1; d < LSIZE; d <<= 1) + { + barrier(CLK_LOCAL_MEM_FENCE); + offset >>= 1; + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; + + lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; + lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step / 4, loc_s1 = loc_s0 + dst_step ; + int loc_sq0 = gid * CONVERT(dst1_step) + i + lid - 1 - pre_invalid * dst1_step / sizeof(TYPE), loc_sq1 = loc_sq0 + CONVERT(dst1_step); + if(lid > 0 && (i+lid) <= rows) + { + lm_sum[0][bf_loc] += sum_t[0]; + lm_sum[1][bf_loc] += sum_t[1]; + lm_sqsum[0][bf_loc] += sqsum_t[0]; + lm_sqsum[1][bf_loc] += sqsum_t[1]; + sum_p = (__local float*)(&(lm_sum[0][bf_loc])); + sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue; + sum[loc_s0 + k * dst_step / 4] = sum_p[k]; + sqsum[loc_sq0 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k]; + } + sum_p = (__local float*)(&(lm_sum[1][bf_loc])); + sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 4 + k + 4 >= cols + pre_invalid) break; + sum[loc_s1 + k * dst_step / 4] = sum_p[k]; + sqsum[loc_sq1 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} + +kernel void integral_rows(__global float4 *srcsum, __global TYPE4 * srcsqsum, __global float *sum , + __global TYPE *sqsum, int rows, int cols, int src_step, int src1_step, int sum_step, + int sqsum_step, int sum_offset, int sqsum_offset) +{ + int lid = get_local_id(0); + int gid = get_group_id(0); + float4 src_t[2], sum_t[2]; + TYPE4 sqsrc_t[2],sqsum_t[2]; + __local float4 lm_sum[2][LSIZE + LOG_LSIZE]; + __local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE]; + __local float *sum_p; + __local TYPE *sqsum_p; + src_step = src_step >> 4; + src1_step = (src1_step / sizeof(TYPE)) >> 2; + for(int i = 0; i < rows; i =i + LSIZE_1) + { + src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2] : (float4)0; + sqsrc_t[0] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid * 2] : (TYPE4)0; + src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2 + 1] : (float4)0; + sqsrc_t[1] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid * 2 + 1] : (TYPE4)0; + + sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); + sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]); + sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); + sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]); + barrier(CLK_LOCAL_MEM_FENCE); + + int bf_loc = lid + GET_CONFLICT_OFFSET(lid); + lm_sum[0][bf_loc] = src_t[0]; + lm_sqsum[0][bf_loc] = sqsrc_t[0]; + + lm_sum[1][bf_loc] = src_t[1]; + lm_sqsum[1][bf_loc] = sqsrc_t[1]; + + int offset = 1; + for(int d = LSIZE >> 1 ; d > 0; d>>=1) + { + barrier(CLK_LOCAL_MEM_FENCE); + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; + } + offset <<= 1; + } + barrier(CLK_LOCAL_MEM_FENCE); + if(lid < 2) + { + lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; + lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0; + } + for(int d = 1; d < LSIZE; d <<= 1) + { + barrier(CLK_LOCAL_MEM_FENCE); + offset >>= 1; + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; + + lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai]; + lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + if(gid == 0 && (i + lid) <= rows) + { + sum[sum_offset + i + lid] = 0; + sqsum[sqsum_offset + i + lid] = 0; + } + if(i + lid == 0) + { + int loc0 = gid * 2 * sum_step; + int loc1 = gid * 2 * CONVERT(sqsum_step); + for(int k = 1; k <= 8; k++) + { + if(gid * 8 + k > cols) break; + sum[sum_offset + loc0 + k * sum_step / 4] = 0; + sqsum[sqsum_offset + loc1 + k * sqsum_step / sizeof(TYPE)] = 0; + } + } + int loc_s0 = sum_offset + gid * 2 * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ; + int loc_sq0 = sqsum_offset + gid * 2 * CONVERT(sqsum_step) + sqsum_step / sizeof(TYPE) + i + lid, loc_sq1 = loc_sq0 + CONVERT(sqsum_step) ; + if(lid > 0 && (i+lid) <= rows) + { + lm_sum[0][bf_loc] += sum_t[0]; + lm_sum[1][bf_loc] += sum_t[1]; + lm_sqsum[0][bf_loc] += sqsum_t[0]; + lm_sqsum[1][bf_loc] += sqsum_t[1]; + sum_p = (__local float*)(&(lm_sum[0][bf_loc])); + sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 8 + k >= cols) break; + sum[loc_s0 + k * sum_step / 4] = sum_p[k]; + sqsum[loc_sq0 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k]; + } + sum_p = (__local float*)(&(lm_sum[1][bf_loc])); + sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 8 + 4 + k >= cols) break; + sum[loc_s1 + k * sum_step / 4] = sum_p[k]; + sqsum[loc_sq1 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} + +#endif diff --git a/modules/imgproc/src/opencl/integral_sum.cl b/modules/imgproc/src/opencl/integral_sum.cl new file mode 100644 index 0000000000..dda0e60186 --- /dev/null +++ b/modules/imgproc/src/opencl/integral_sum.cl @@ -0,0 +1,413 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Shengen Yan,yanshengen@gmail.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 materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors as is and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including 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 DOUBLE_SUPPORT +#ifdef cl_amd_fp64 +#pragma OPENCL EXTENSION cl_amd_fp64:enable +#elif defined (cl_khr_fp64) +#pragma OPENCL EXTENSION cl_khr_fp64:enable +#endif +#endif + +#define LSIZE 256 +#define LSIZE_1 255 +#define LSIZE_2 254 +#define HF_LSIZE 128 +#define LOG_LSIZE 8 +#define LOG_NUM_BANKS 5 +#define NUM_BANKS 32 +#define GET_CONFLICT_OFFSET(lid) ((lid) >> LOG_NUM_BANKS) + +#if sdepth == 4 + +kernel void integral_sum_cols(__global uchar4 *src, __global int *sum, + int src_offset, int pre_invalid, int rows, int cols, int src_step, int dst_step) +{ + int lid = get_local_id(0); + int gid = get_group_id(0); + int4 src_t[2], sum_t[2]; + __local int4 lm_sum[2][LSIZE + LOG_LSIZE]; + __local int* sum_p; + src_step = src_step >> 2; + gid = gid << 1; + for(int i = 0; i < rows; i =i + LSIZE_1) + { + src_t[0] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + gid]) : 0); + src_t[1] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + gid + 1]) : 0); + + sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); + sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); + barrier(CLK_LOCAL_MEM_FENCE); + + int bf_loc = lid + GET_CONFLICT_OFFSET(lid); + lm_sum[0][bf_loc] = src_t[0]; + + lm_sum[1][bf_loc] = src_t[1]; + + int offset = 1; + for(int d = LSIZE >> 1 ; d > 0; d>>=1) + { + barrier(CLK_LOCAL_MEM_FENCE); + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + } + offset <<= 1; + } + barrier(CLK_LOCAL_MEM_FENCE); + if(lid < 2) + { + lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; + } + for(int d = 1; d < LSIZE; d <<= 1) + { + barrier(CLK_LOCAL_MEM_FENCE); + offset >>= 1; + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + if(lid > 0 && (i+lid) <= rows) + { + int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step / 4, loc_s1 = loc_s0 + dst_step ; + lm_sum[0][bf_loc] += sum_t[0]; + lm_sum[1][bf_loc] += sum_t[1]; + sum_p = (__local int*)(&(lm_sum[0][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue; + sum[loc_s0 + k * dst_step / 4] = sum_p[k]; + } + sum_p = (__local int*)(&(lm_sum[1][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 4 + k + 4 >= cols + pre_invalid) break; + sum[loc_s1 + k * dst_step / 4] = sum_p[k]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} + +kernel void integral_sum_rows(__global int4 *srcsum, __global int *sum, + int rows, int cols, int src_step, int sum_step, int sum_offset) +{ + int lid = get_local_id(0); + int gid = get_group_id(0); + int4 src_t[2], sum_t[2]; + __local int4 lm_sum[2][LSIZE + LOG_LSIZE]; + __local int *sum_p; + src_step = src_step >> 4; + for(int i = 0; i < rows; i =i + LSIZE_1) + { + src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2] : 0; + src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2 + 1] : 0; + + sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); + sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); + barrier(CLK_LOCAL_MEM_FENCE); + + int bf_loc = lid + GET_CONFLICT_OFFSET(lid); + lm_sum[0][bf_loc] = src_t[0]; + + lm_sum[1][bf_loc] = src_t[1]; + + int offset = 1; + for(int d = LSIZE >> 1 ; d > 0; d>>=1) + { + barrier(CLK_LOCAL_MEM_FENCE); + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + } + offset <<= 1; + } + barrier(CLK_LOCAL_MEM_FENCE); + if(lid < 2) + { + lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; + } + for(int d = 1; d < LSIZE; d <<= 1) + { + barrier(CLK_LOCAL_MEM_FENCE); + offset >>= 1; + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + if(gid == 0 && (i + lid) <= rows) + { + sum[sum_offset + i + lid] = 0; + } + if(i + lid == 0) + { + int loc0 = gid * 2 * sum_step; + for(int k = 1; k <= 8; k++) + { + if(gid * 8 + k > cols) break; + sum[sum_offset + loc0 + k * sum_step / 4] = 0; + } + } + + if(lid > 0 && (i+lid) <= rows) + { + int loc_s0 = sum_offset + gid * 2 * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ; + lm_sum[0][bf_loc] += sum_t[0]; + lm_sum[1][bf_loc] += sum_t[1]; + sum_p = (__local int*)(&(lm_sum[0][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 8 + k >= cols) break; + sum[loc_s0 + k * sum_step / 4] = sum_p[k]; + } + sum_p = (__local int*)(&(lm_sum[1][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 8 + 4 + k >= cols) break; + sum[loc_s1 + k * sum_step / 4] = sum_p[k]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} + +#elif sdepth == 5 + +kernel void integral_sum_cols(__global uchar4 *src, __global float *sum, + int src_offset, int pre_invalid, int rows, int cols, int src_step, int dst_step) +{ + int lid = get_local_id(0); + int gid = get_group_id(0); + float4 src_t[2], sum_t[2]; + __local float4 lm_sum[2][LSIZE + LOG_LSIZE]; + __local float* sum_p; + src_step = src_step >> 2; + gid = gid << 1; + for(int i = 0; i < rows; i =i + LSIZE_1) + { + src_t[0] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + gid]) : (float4)0); + src_t[1] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + gid + 1]) : (float4)0); + + sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); + sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); + barrier(CLK_LOCAL_MEM_FENCE); + + int bf_loc = lid + GET_CONFLICT_OFFSET(lid); + lm_sum[0][bf_loc] = src_t[0]; + + lm_sum[1][bf_loc] = src_t[1]; + + int offset = 1; + for(int d = LSIZE >> 1 ; d > 0; d>>=1) + { + barrier(CLK_LOCAL_MEM_FENCE); + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + } + offset <<= 1; + } + barrier(CLK_LOCAL_MEM_FENCE); + if(lid < 2) + { + lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; + } + for(int d = 1; d < LSIZE; d <<= 1) + { + barrier(CLK_LOCAL_MEM_FENCE); + offset >>= 1; + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + if(lid > 0 && (i+lid) <= rows) + { + int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step / 4, loc_s1 = loc_s0 + dst_step ; + lm_sum[0][bf_loc] += sum_t[0]; + lm_sum[1][bf_loc] += sum_t[1]; + sum_p = (__local float*)(&(lm_sum[0][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue; + sum[loc_s0 + k * dst_step / 4] = sum_p[k]; + } + sum_p = (__local float*)(&(lm_sum[1][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 4 + k + 4 >= cols + pre_invalid) break; + sum[loc_s1 + k * dst_step / 4] = sum_p[k]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} + +kernel void integral_sum_rows(__global float4 *srcsum, __global float *sum, + int rows, int cols, int src_step, int sum_step, int sum_offset) +{ + int lid = get_local_id(0); + int gid = get_group_id(0); + float4 src_t[2], sum_t[2]; + __local float4 lm_sum[2][LSIZE + LOG_LSIZE]; + __local float *sum_p; + src_step = src_step >> 4; + for(int i = 0; i < rows; i =i + LSIZE_1) + { + src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2] : (float4)0; + src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2 + 1] : (float4)0; + + sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]); + sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]); + barrier(CLK_LOCAL_MEM_FENCE); + + int bf_loc = lid + GET_CONFLICT_OFFSET(lid); + lm_sum[0][bf_loc] = src_t[0]; + + lm_sum[1][bf_loc] = src_t[1]; + + int offset = 1; + for(int d = LSIZE >> 1 ; d > 0; d>>=1) + { + barrier(CLK_LOCAL_MEM_FENCE); + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + } + offset <<= 1; + } + barrier(CLK_LOCAL_MEM_FENCE); + if(lid < 2) + { + lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0; + } + for(int d = 1; d < LSIZE; d <<= 1) + { + barrier(CLK_LOCAL_MEM_FENCE); + offset >>= 1; + int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset; + ai += GET_CONFLICT_OFFSET(ai); + bi += GET_CONFLICT_OFFSET(bi); + + if((lid & 127) < d) + { + lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai]; + lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + if(gid == 0 && (i + lid) <= rows) + { + sum[sum_offset + i + lid] = 0; + } + if(i + lid == 0) + { + int loc0 = gid * 2 * sum_step; + for(int k = 1; k <= 8; k++) + { + if(gid * 8 + k > cols) break; + sum[sum_offset + loc0 + k * sum_step / 4] = 0; + } + } + + if(lid > 0 && (i+lid) <= rows) + { + int loc_s0 = sum_offset + gid * 2 * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ; + lm_sum[0][bf_loc] += sum_t[0]; + lm_sum[1][bf_loc] += sum_t[1]; + sum_p = (__local float*)(&(lm_sum[0][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 8 + k >= cols) break; + sum[loc_s0 + k * sum_step / 4] = sum_p[k]; + } + sum_p = (__local float*)(&(lm_sum[1][bf_loc])); + for(int k = 0; k < 4; k++) + { + if(gid * 8 + 4 + k >= cols) break; + sum[loc_s1 + k * sum_step / 4] = sum_p[k]; + } + } + barrier(CLK_LOCAL_MEM_FENCE); + } +} + +#endif diff --git a/modules/imgproc/src/sumpixels.cpp b/modules/imgproc/src/sumpixels.cpp index 219f28d62e..f353945df7 100644 --- a/modules/imgproc/src/sumpixels.cpp +++ b/modules/imgproc/src/sumpixels.cpp @@ -41,6 +41,8 @@ //M*/ #include "precomp.hpp" +#include "opencl_kernels.hpp" + #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) static IppStatus sts = ippInit(); #endif @@ -215,28 +217,139 @@ static void integral_##suffix( T* src, size_t srcstep, ST* sum, size_t sumstep, { integral_(src, srcstep, sum, sumstep, sqsum, sqsumstep, tilted, tiltedstep, size, cn); } DEF_INTEGRAL_FUNC(8u32s, uchar, int, double) -DEF_INTEGRAL_FUNC(8u32f, uchar, float, double) -DEF_INTEGRAL_FUNC(8u64f, uchar, double, double) -DEF_INTEGRAL_FUNC(32f, float, float, double) -DEF_INTEGRAL_FUNC(32f64f, float, double, double) -DEF_INTEGRAL_FUNC(64f, double, double, double) +DEF_INTEGRAL_FUNC(8u32f64f, uchar, float, double) +DEF_INTEGRAL_FUNC(8u64f64f, uchar, double, double) +DEF_INTEGRAL_FUNC(32f32f64f, float, float, double) +DEF_INTEGRAL_FUNC(32f64f64f, float, double, double) +DEF_INTEGRAL_FUNC(64f64f64f, double, double, double) + +DEF_INTEGRAL_FUNC(8u32s32f, uchar, int, float) +DEF_INTEGRAL_FUNC(8u32f32f, uchar, float, float) +DEF_INTEGRAL_FUNC(32f32f32f, float, float, float) typedef void (*IntegralFunc)(const uchar* src, size_t srcstep, uchar* sum, size_t sumstep, uchar* sqsum, size_t sqsumstep, uchar* tilted, size_t tstep, Size size, int cn ); +enum { vlen = 4 }; + +static bool ocl_integral( InputArray _src, OutputArray _sum, int sdepth ) +{ + if ( _src.type() != CV_8UC1 || _src.step() % vlen != 0 || _src.offset() % vlen != 0 || + !(sdepth == CV_32S || sdepth == CV_32F) ) + return false; + + ocl::Kernel k1("integral_sum_cols", ocl::imgproc::integral_sum_oclsrc, + format("-D sdepth=%d", sdepth)); + if (k1.empty()) + return false; + + Size size = _src.size(), t_size = Size(((size.height + vlen - 1) / vlen) * vlen, size.width), + ssize(size.width + 1, size.height + 1); + _sum.create(ssize, sdepth); + UMat src = _src.getUMat(), t_sum(t_size, sdepth), sum = _sum.getUMat(); + t_sum = t_sum(Range::all(), Range(0, size.height)); + + int offset = src.offset / vlen, pre_invalid = src.offset % vlen; + int vcols = (pre_invalid + src.cols + vlen - 1) / vlen; + int sum_offset = sum.offset / vlen; + + k1.args(ocl::KernelArg::PtrReadOnly(src), ocl::KernelArg::PtrWriteOnly(t_sum), + offset, pre_invalid, src.rows, src.cols, (int)src.step, (int)t_sum.step); + size_t gt = ((vcols + 1) / 2) * 256, lt = 256; + if (!k1.run(1, >, <, false)) + return false; + + ocl::Kernel k2("integral_sum_rows", ocl::imgproc::integral_sum_oclsrc, + format("-D sdepth=%d", sdepth)); + k2.args(ocl::KernelArg::PtrReadWrite(t_sum), ocl::KernelArg::PtrWriteOnly(sum), + t_sum.rows, t_sum.cols, (int)t_sum.step, (int)sum.step, sum_offset); + + size_t gt2 = t_sum.cols * 32, lt2 = 256; + return k2.run(1, >2, <2, false); +} + +static bool ocl_integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, int sdepth, int sqdepth ) +{ + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; + + if ( _src.type() != CV_8UC1 || _src.step() % vlen != 0 || _src.offset() % vlen != 0 || + (!doubleSupport && (sdepth == CV_64F || sqdepth == CV_64F)) ) + return false; + + char cvt[40]; + String opts = format("-D sdepth=%d -D sqdepth=%d -D TYPE=%s -D TYPE4=%s4 -D convert_TYPE4=%s%s", + sdepth, sqdepth, ocl::typeToStr(sqdepth), ocl::typeToStr(sqdepth), + ocl::convertTypeStr(sdepth, sqdepth, 4, cvt), + doubleSupport ? " -D DOUBLE_SUPPORT" : ""); + + ocl::Kernel k1("integral_cols", ocl::imgproc::integral_sqrsum_oclsrc, opts); + if (k1.empty()) + return false; + + Size size = _src.size(), dsize = Size(size.width + 1, size.height + 1), + t_size = Size(((size.height + vlen - 1) / vlen) * vlen, size.width); + UMat src = _src.getUMat(), t_sum(t_size, sdepth), t_sqsum(t_size, sqdepth); + t_sum = t_sum(Range::all(), Range(0, size.height)); + t_sqsum = t_sqsum(Range::all(), Range(0, size.height)); + + _sum.create(dsize, sdepth); + _sqsum.create(dsize, sqdepth); + UMat sum = _sum.getUMat(), sqsum = _sqsum.getUMat(); + + int offset = src.offset / vlen; + int pre_invalid = src.offset % vlen; + int vcols = (pre_invalid + src.cols + vlen - 1) / vlen; + int sum_offset = sum.offset / sum.elemSize(); + int sqsum_offset = sqsum.offset / sqsum.elemSize(); + CV_Assert(sqsum.offset % sqsum.elemSize() == 0); + + k1.args(ocl::KernelArg::PtrReadOnly(src), ocl::KernelArg::PtrWriteOnly(t_sum), + ocl::KernelArg::PtrWriteOnly(t_sqsum), offset, pre_invalid, src.rows, + src.cols, (int)src.step, (int)t_sum.step, (int)t_sqsum.step); + + size_t gt = ((vcols + 1) / 2) * 256, lt = 256; + if (!k1.run(1, >, <, false)) + return false; + + ocl::Kernel k2("integral_rows", ocl::imgproc::integral_sqrsum_oclsrc, opts); + if (k2.empty()) + return false; + + k2.args(ocl::KernelArg::PtrReadOnly(t_sum), ocl::KernelArg::PtrReadOnly(t_sqsum), + ocl::KernelArg::PtrWriteOnly(sum), ocl::KernelArg::PtrWriteOnly(sqsum), + t_sum.rows, t_sum.cols, (int)t_sum.step, (int)t_sqsum.step, + (int)sum.step, (int)sqsum.step, sum_offset, sqsum_offset); + + size_t gt2 = t_sum.cols * 32, lt2 = 256; + return k2.run(1, >2, <2, false); +} + } -void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, OutputArray _tilted, int sdepth ) +void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, OutputArray _tilted, int sdepth, int sqdepth ) { - Mat src = _src.getMat(), sum, sqsum, tilted; - int depth = src.depth(), cn = src.channels(); - Size isize(src.cols + 1, src.rows+1); - + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); if( sdepth <= 0 ) sdepth = depth == CV_8U ? CV_32S : CV_64F; - sdepth = CV_MAT_DEPTH(sdepth); + if ( sqdepth <= 0 ) + sqdepth = CV_64F; + sdepth = CV_MAT_DEPTH(sdepth), sqdepth = CV_MAT_DEPTH(sqdepth); + + if (ocl::useOpenCL() && _sum.isUMat() && !_tilted.needed()) + { + if (!_sqsum.needed()) + { + if (ocl_integral(_src, _sum, sdepth)) + return; + } + else if (_sqsum.isUMat()) + { + if (ocl_integral(_src, _sum, _sqsum, sdepth, sqdepth)) + return; + } + } #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) if( ( depth == CV_8U ) && ( !_tilted.needed() ) ) @@ -248,9 +361,9 @@ void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, Output IppiSize srcRoiSize = ippiSize( src.cols, src.rows ); _sum.create( isize, CV_MAKETYPE( sdepth, cn ) ); sum = _sum.getMat(); - if( _sqsum.needed() ) + if( _sqsum.needed() && sqdepth == CV_64F ) { - _sqsum.create( isize, CV_MAKETYPE( CV_64F, cn ) ); + _sqsum.create( isize, CV_MAKETYPE( sqdepth, cn ) ); sqsum = _sqsum.getMat(); ippiSqrIntegral_8u32f64f_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32f*)sum.data, (int)sum.step, (Ipp64f*)sqsum.data, (int)sqsum.step, srcRoiSize, 0, 0 ); } @@ -268,9 +381,9 @@ void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, Output IppiSize srcRoiSize = ippiSize( src.cols, src.rows ); _sum.create( isize, CV_MAKETYPE( sdepth, cn ) ); sum = _sum.getMat(); - if( _sqsum.needed() ) + if( _sqsum.needed() && sqdepth == CV_64F ) { - _sqsum.create( isize, CV_MAKETYPE( CV_64F, cn ) ); + _sqsum.create( isize, CV_MAKETYPE( sqdepth, cn ) ); sqsum = _sqsum.getMat(); ippiSqrIntegral_8u32s64f_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32s*)sum.data, (int)sum.step, (Ipp64f*)sqsum.data, (int)sqsum.step, srcRoiSize, 0, 0 ); } @@ -284,8 +397,15 @@ void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, Output } #endif + Size ssize = _src.size(), isize(ssize.width + 1, ssize.height + 1); _sum.create( isize, CV_MAKETYPE(sdepth, cn) ); - sum = _sum.getMat(); + Mat src = _src.getMat(), sum =_sum.getMat(), sqsum, tilted; + + if( _sqsum.needed() ) + { + _sqsum.create( isize, CV_MAKETYPE(sqdepth, cn) ); + sqsum = _sqsum.getMat(); + } if( _tilted.needed() ) { @@ -293,26 +413,25 @@ void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, Output tilted = _tilted.getMat(); } - if( _sqsum.needed() ) - { - _sqsum.create( isize, CV_MAKETYPE(CV_64F, cn) ); - sqsum = _sqsum.getMat(); - } - IntegralFunc func = 0; - - if( depth == CV_8U && sdepth == CV_32S ) + if( depth == CV_8U && sdepth == CV_32S && sqdepth == CV_64F ) func = (IntegralFunc)GET_OPTIMIZED(integral_8u32s); - else if( depth == CV_8U && sdepth == CV_32F ) - func = (IntegralFunc)integral_8u32f; - else if( depth == CV_8U && sdepth == CV_64F ) - func = (IntegralFunc)integral_8u64f; - else if( depth == CV_32F && sdepth == CV_32F ) - func = (IntegralFunc)integral_32f; - else if( depth == CV_32F && sdepth == CV_64F ) - func = (IntegralFunc)integral_32f64f; - else if( depth == CV_64F && sdepth == CV_64F ) - func = (IntegralFunc)integral_64f; + else if( depth == CV_8U && sdepth == CV_32S && sqdepth == CV_32F ) + func = (IntegralFunc)integral_8u32s32f; + else if( depth == CV_8U && sdepth == CV_32F && sqdepth == CV_64F ) + func = (IntegralFunc)integral_8u32f64f; + else if( depth == CV_8U && sdepth == CV_32F && sqdepth == CV_32F ) + func = (IntegralFunc)integral_8u32f32f; + else if( depth == CV_8U && sdepth == CV_64F && sqdepth == CV_64F ) + func = (IntegralFunc)integral_8u64f64f; + else if( depth == CV_32F && sdepth == CV_32F && sqdepth == CV_64F ) + func = (IntegralFunc)integral_32f32f64f; + else if( depth == CV_32F && sdepth == CV_32F && sqdepth == CV_32F ) + func = (IntegralFunc)integral_32f32f32f; + else if( depth == CV_32F && sdepth == CV_64F && sqdepth == CV_64F ) + func = (IntegralFunc)integral_32f64f64f; + else if( depth == CV_64F && sdepth == CV_64F && sqdepth == CV_64F ) + func = (IntegralFunc)integral_64f64f64f; else CV_Error( CV_StsUnsupportedFormat, "" ); @@ -325,9 +444,9 @@ void cv::integral( InputArray src, OutputArray sum, int sdepth ) integral( src, sum, noArray(), noArray(), sdepth ); } -void cv::integral( InputArray src, OutputArray sum, OutputArray sqsum, int sdepth ) +void cv::integral( InputArray src, OutputArray sum, OutputArray sqsum, int sdepth, int sqdepth ) { - integral( src, sum, sqsum, noArray(), sdepth ); + integral( src, sum, sqsum, noArray(), sdepth, sqdepth ); } diff --git a/modules/imgproc/test/ocl/test_imgproc.cpp b/modules/imgproc/test/ocl/test_imgproc.cpp index ae833406f0..9089b55927 100644 --- a/modules/imgproc/test/ocl/test_imgproc.cpp +++ b/modules/imgproc/test/ocl/test_imgproc.cpp @@ -271,15 +271,50 @@ OCL_TEST_P(CornerHarris, DISABLED_Mat) struct Integral : public ImgprocTestBase { - int sdepth; + int sdepth, sqdepth; + + TEST_DECLARE_OUTPUT_PARAMETER(dst2) virtual void SetUp() { type = GET_PARAM(0); - blockSize = GET_PARAM(1); - sdepth = GET_PARAM(2); + sdepth = GET_PARAM(1); + sqdepth = GET_PARAM(2); useRoi = GET_PARAM(3); } + + virtual void random_roi() + { + ASSERT_EQ(CV_MAT_CN(type), 1); + + Size roiSize = randomSize(1, MAX_VALUE), isize = Size(roiSize.width + 1, roiSize.height + 1); + Border srcBorder = randomBorder(0, useRoi ? 2 : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, type, 5, 256); + + Border dstBorder = randomBorder(0, useRoi ? 2 : 0); + randomSubMat(dst, dst_roi, isize, dstBorder, sdepth, 5, 16); + + Border dst2Border = randomBorder(0, useRoi ? 2 : 0); + randomSubMat(dst2, dst2_roi, isize, dst2Border, sqdepth, 5, 16); + + UMAT_UPLOAD_INPUT_PARAMETER(src) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst2) + } + + void Near2(double threshold = 0.0, bool relative = false) + { + if (relative) + { + EXPECT_MAT_NEAR_RELATIVE(dst2, udst2, threshold); + EXPECT_MAT_NEAR_RELATIVE(dst2_roi, udst2_roi, threshold); + } + else + { + EXPECT_MAT_NEAR(dst2, udst2, threshold); + EXPECT_MAT_NEAR(dst2_roi, udst2_roi, threshold); + } + } }; OCL_TEST_P(Integral, Mat1) @@ -297,19 +332,15 @@ OCL_TEST_P(Integral, Mat1) OCL_TEST_P(Integral, Mat2) { - Mat dst1; - UMat udst1; - for (int j = 0; j < test_loop_times; j++) { random_roi(); - OCL_OFF(cv::integral(src_roi, dst_roi, dst1, sdepth)); - OCL_ON(cv::integral(usrc_roi, udst_roi, udst1, sdepth)); + OCL_OFF(cv::integral(src_roi, dst_roi, dst2_roi, sdepth, sqdepth)); + OCL_ON(cv::integral(usrc_roi, udst_roi, udst2_roi, sdepth, sqdepth)); Near(); - if (cv::ocl::Device::getDefault().doubleFPConfig() > 0) - EXPECT_MAT_NEAR(dst1, udst1, 0.); + sqdepth == CV_32F ? Near2(1e-6, true) : Near2(); } } @@ -412,19 +443,21 @@ OCL_INSTANTIATE_TEST_CASE_P(Imgproc, EqualizeHist, Combine( OCL_INSTANTIATE_TEST_CASE_P(Imgproc, CornerMinEigenVal, Combine( Values((MatType)CV_8UC1, (MatType)CV_32FC1), Values(3, 5), - Values((int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, (int)BORDER_REFLECT101), + Values((BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE, + (BorderType)BORDER_REFLECT, (BorderType)BORDER_REFLECT101), Bool())); OCL_INSTANTIATE_TEST_CASE_P(Imgproc, CornerHarris, Combine( Values((MatType)CV_8UC1, CV_32FC1), Values(3, 5), - Values( (int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, (int)BORDER_REFLECT_101), + Values( (BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE, + (BorderType)BORDER_REFLECT, (BorderType)BORDER_REFLECT_101), Bool())); OCL_INSTANTIATE_TEST_CASE_P(Imgproc, Integral, Combine( Values((MatType)CV_8UC1), // TODO does not work with CV_32F, CV_64F - Values(0), // not used - Values((MatType)CV_32SC1, (MatType)CV_32FC1), + Values(CV_32SC1, CV_32FC1), // desired sdepth + Values(CV_32FC1, CV_64FC1), // desired sqdepth Bool())); OCL_INSTANTIATE_TEST_CASE_P(Imgproc, Threshold, Combine( diff --git a/modules/java/android_test/src/org/opencv/test/imgproc/ImgprocTest.java b/modules/java/android_test/src/org/opencv/test/imgproc/ImgprocTest.java index 7971ea2f1f..15ea13b168 100644 --- a/modules/java/android_test/src/org/opencv/test/imgproc/ImgprocTest.java +++ b/modules/java/android_test/src/org/opencv/test/imgproc/ImgprocTest.java @@ -1225,7 +1225,7 @@ public class ImgprocTest extends OpenCVTestCase { expSqsum.put(2, 0, 0, 18, 36, 54); expSqsum.put(3, 0, 0, 27, 54, 81); - Imgproc.integral2(src, sum, sqsum, CvType.CV_64F); + Imgproc.integral2(src, sum, sqsum, CvType.CV_64F, CvType.CV_64F); assertMatEqual(expSum, sum, EPS); assertMatEqual(expSqsum, sqsum, EPS); @@ -1274,7 +1274,7 @@ public class ImgprocTest extends OpenCVTestCase { expTilted.put(0, 0, 0, 0); expTilted.put(1, 0, 0, 1); - Imgproc.integral3(src, sum, sqsum, tilted, CvType.CV_64F); + Imgproc.integral3(src, sum, sqsum, tilted, CvType.CV_64F, CvType.CV_64F); assertMatEqual(expSum, sum, EPS); assertMatEqual(expSqsum, sqsum, EPS); From 8a48802decd4cf355cc0646ad3cd12af40af0bc8 Mon Sep 17 00:00:00 2001 From: Dirk Van Haerenborgh Date: Fri, 6 Dec 2013 10:20:29 +0100 Subject: [PATCH 58/97] Enable GStreamer 1.x support by default. GStreamer 1.x is universally available, and with 0.10 being deprecated, there should be no reason to default to 0.10 stil. --- CMakeLists.txt | 2 +- cmake/OpenCVFindLibsVideo.cmake | 44 ++++++++++++++++----------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 45e5b915fc..2e27852de9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,7 +124,7 @@ OCV_OPTION(WITH_EIGEN "Include Eigen2/Eigen3 support" ON) OCV_OPTION(WITH_VFW "Include Video for Windows support" ON IF WIN32 ) OCV_OPTION(WITH_FFMPEG "Include FFMPEG support" ON IF (NOT ANDROID AND NOT IOS)) OCV_OPTION(WITH_GSTREAMER "Include Gstreamer support" ON IF (UNIX AND NOT APPLE AND NOT ANDROID) ) -OCV_OPTION(WITH_GSTREAMER_1_X "Include Gstreamer 1.x support" OFF) +OCV_OPTION(WITH_GSTREAMER_0_10 "Enable Gstreamer 0.10 support (instead of 1.x)" OFF ) OCV_OPTION(WITH_GTK "Include GTK support" ON IF (UNIX AND NOT APPLE AND NOT ANDROID) ) OCV_OPTION(WITH_IPP "Include Intel IPP support" OFF IF (MSVC OR X86 OR X86_64) ) OCV_OPTION(WITH_JASPER "Include JPEG2K support" ON IF (NOT IOS) ) diff --git a/cmake/OpenCVFindLibsVideo.cmake b/cmake/OpenCVFindLibsVideo.cmake index 737331ecf5..807f4fbbf2 100644 --- a/cmake/OpenCVFindLibsVideo.cmake +++ b/cmake/OpenCVFindLibsVideo.cmake @@ -12,28 +12,8 @@ endif(WITH_VFW) # --- GStreamer --- ocv_clear_vars(HAVE_GSTREAMER) -# try to find gstreamer 0.10 first -if(WITH_GSTREAMER AND NOT WITH_GSTREAMER_1_X) - CHECK_MODULE(gstreamer-base-0.10 HAVE_GSTREAMER_BASE) - CHECK_MODULE(gstreamer-video-0.10 HAVE_GSTREAMER_VIDEO) - CHECK_MODULE(gstreamer-app-0.10 HAVE_GSTREAMER_APP) - CHECK_MODULE(gstreamer-riff-0.10 HAVE_GSTREAMER_RIFF) - CHECK_MODULE(gstreamer-pbutils-0.10 HAVE_GSTREAMER_PBUTILS) - - if(HAVE_GSTREAMER_BASE AND HAVE_GSTREAMER_VIDEO AND HAVE_GSTREAMER_APP AND HAVE_GSTREAMER_RIFF AND HAVE_GSTREAMER_PBUTILS) - set(HAVE_GSTREAMER TRUE) - set(GSTREAMER_BASE_VERSION ${ALIASOF_gstreamer-base-0.10_VERSION}) - set(GSTREAMER_VIDEO_VERSION ${ALIASOF_gstreamer-video-0.10_VERSION}) - set(GSTREAMER_APP_VERSION ${ALIASOF_gstreamer-app-0.10_VERSION}) - set(GSTREAMER_RIFF_VERSION ${ALIASOF_gstreamer-riff-0.10_VERSION}) - set(GSTREAMER_PBUTILS_VERSION ${ALIASOF_gstreamer-pbutils-0.10_VERSION}) - endif() - -endif(WITH_GSTREAMER AND NOT WITH_GSTREAMER_1_X) - -# if gstreamer 0.10 was not found, or we specified we wanted 1.x, try to find it -if(WITH_GSTREAMER_1_X OR NOT HAVE_GSTREAMER) - #check for 1.x +# try to find gstreamer 1.x first +if(WITH_GSTREAMER AND NOT WITH_GSTREAMER_0_10) CHECK_MODULE(gstreamer-base-1.0 HAVE_GSTREAMER_BASE) CHECK_MODULE(gstreamer-video-1.0 HAVE_GSTREAMER_VIDEO) CHECK_MODULE(gstreamer-app-1.0 HAVE_GSTREAMER_APP) @@ -49,7 +29,25 @@ if(WITH_GSTREAMER_1_X OR NOT HAVE_GSTREAMER) set(GSTREAMER_PBUTILS_VERSION ${ALIASOF_gstreamer-pbutils-1.0_VERSION}) endif() -endif(WITH_GSTREAMER_1_X OR NOT HAVE_GSTREAMER) +endif(WITH_GSTREAMER AND NOT WITH_GSTREAMER_0_10) + +# if gstreamer 1.x was not found, or we specified we wanted 0.10, try to find it +if(WITH_GSTREAMER_0_10 OR NOT HAVE_GSTREAMER) + CHECK_MODULE(gstreamer-base-0.10 HAVE_GSTREAMER_BASE) + CHECK_MODULE(gstreamer-video-0.10 HAVE_GSTREAMER_VIDEO) + CHECK_MODULE(gstreamer-app-0.10 HAVE_GSTREAMER_APP) + CHECK_MODULE(gstreamer-riff-0.10 HAVE_GSTREAMER_RIFF) + CHECK_MODULE(gstreamer-pbutils-0.10 HAVE_GSTREAMER_PBUTILS) + + if(HAVE_GSTREAMER_BASE AND HAVE_GSTREAMER_VIDEO AND HAVE_GSTREAMER_APP AND HAVE_GSTREAMER_RIFF AND HAVE_GSTREAMER_PBUTILS) + set(HAVE_GSTREAMER TRUE) + set(GSTREAMER_BASE_VERSION ${ALIASOF_gstreamer-base-0.10_VERSION}) + set(GSTREAMER_VIDEO_VERSION ${ALIASOF_gstreamer-video-0.10_VERSION}) + set(GSTREAMER_APP_VERSION ${ALIASOF_gstreamer-app-0.10_VERSION}) + set(GSTREAMER_RIFF_VERSION ${ALIASOF_gstreamer-riff-0.10_VERSION}) + set(GSTREAMER_PBUTILS_VERSION ${ALIASOF_gstreamer-pbutils-0.10_VERSION}) + endif() +endif(WITH_GSTREAMER_0_10 OR NOT HAVE_GSTREAMER) # --- unicap --- ocv_clear_vars(HAVE_UNICAP) From 894724eaf0641a2b511797dbc28cc5a97c486fe0 Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Fri, 6 Dec 2013 14:49:36 +0400 Subject: [PATCH 59/97] minor improvements --- samples/ocl/facedetect.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/samples/ocl/facedetect.cpp b/samples/ocl/facedetect.cpp index 78a0775151..fbb08cb1e5 100644 --- a/samples/ocl/facedetect.cpp +++ b/samples/ocl/facedetect.cpp @@ -190,18 +190,21 @@ static void detectFaces(std::string fileName) cascade.detectMultiScale(d_img, oclfaces, 1.1, 3, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30), Size(0, 0)); for(unsigned int i = 0; i 0 && outputName[n-1] != '.') - n--; - if( n == 0 ) + std::string::size_type pos = outputName.rfind('.'); + std::string outputNameTid = outputName + '-' + std::to_string(_threadid); + if(pos == std::string::npos) { std::cout << "Invalid output file name: " << outputName << std::endl; - return; } - - imwrite(outputName.substr(0,n-1) + "_" + std::to_string(_threadid) + outputName.substr(n-1, outputName.length()-1), img); + else + { + outputNameTid = outputName.substr(0, pos) + "_" + std::to_string(_threadid) + outputName.substr(pos); + imwrite(outputNameTid, img); + } + imshow(outputNameTid, img); + waitKey(0); } static void facedetect_multithreading(int nthreads) @@ -212,8 +215,6 @@ static void facedetect_multithreading(int nthreads) threads.push_back(std::thread(detectFaces, inputName)); for(int i = 0; i Date: Fri, 6 Dec 2013 13:29:53 +0400 Subject: [PATCH 60/97] fixed warnings --- modules/photo/doc/cloning.rst | 4 ++-- modules/photo/doc/npr.rst | 8 ++++---- modules/photo/include/opencv2/photo.hpp | 14 +++++++------- modules/photo/src/contrast_preserve.cpp | 2 +- modules/photo/src/contrast_preserve.hpp | 21 +++++++++++---------- modules/photo/src/npr.cpp | 2 +- modules/photo/test/test_cloning.cpp | 2 +- modules/photo/test/test_npr.cpp | 2 +- samples/cpp/cloning_demo.cpp | 2 +- samples/cpp/npr_demo.cpp | 2 +- 10 files changed, 30 insertions(+), 29 deletions(-) diff --git a/modules/photo/doc/cloning.rst b/modules/photo/doc/cloning.rst index 48c5b24ba1..384c6b676a 100644 --- a/modules/photo/doc/cloning.rst +++ b/modules/photo/doc/cloning.rst @@ -39,7 +39,7 @@ colorChange ----------- Given an original color image, two differently colored versions of this image can be mixed seamlessly. -.. ocv:function:: void colorChange( InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, float green_mul = 1.0, float blue_mul = 1.0) +.. ocv:function:: void colorChange( InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0f, float green_mul = 1.0f, float blue_mul = 1.0f) :param src: Input 8-bit 3-channel image. @@ -61,7 +61,7 @@ illuminationChange Applying an appropriate non-linear transformation to the gradient field inside the selection and then integrating back with a Poisson solver, modifies locally the apparent illumination of an image. -.. ocv:function:: void illuminationChange(InputArray src, InputArray mask, OutputArray dst, float alpha = 0.2, float beta = 0.4) +.. ocv:function:: void illuminationChange(InputArray src, InputArray mask, OutputArray dst, float alpha = 0.2f, float beta = 0.4f) :param src: Input 8-bit 3-channel image. diff --git a/modules/photo/doc/npr.rst b/modules/photo/doc/npr.rst index 48e2db2a7d..123c946c2a 100644 --- a/modules/photo/doc/npr.rst +++ b/modules/photo/doc/npr.rst @@ -8,7 +8,7 @@ edgePreservingFilter Filtering is the fundamental operation in image and video processing. Edge-preserving smoothing filters are used in many different applications. -.. ocv:function:: void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4) +.. ocv:function:: void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4f) :param src: Input 8-bit 3-channel image. @@ -29,7 +29,7 @@ detailEnhance ------------- This filter enhances the details of a particular image. -.. ocv:function:: void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, float sigma_r = 0.15) +.. ocv:function:: void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, float sigma_r = 0.15f) :param src: Input 8-bit 3-channel image. @@ -44,7 +44,7 @@ pencilSketch ------------ Pencil-like non-photorealistic line drawing -.. ocv:function:: void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02) +.. ocv:function:: void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, float sigma_s = 60, float sigma_r = 0.07f, float shade_factor = 0.02f) :param src: Input 8-bit 3-channel image. @@ -63,7 +63,7 @@ stylization ----------- Stylization aims to produce digital imagery with a wide variety of effects not focused on photorealism. Edge-aware filters are ideal for stylization, as they can abstract regions of low contrast while preserving, or enhancing, high-contrast features. -.. ocv:function:: void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45) +.. ocv:function:: void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45f) :param src: Input 8-bit 3-channel image. diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 7ca933c3f6..f0e3f8ec8a 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -306,27 +306,27 @@ CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray co CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, OutputArray blend, int flags); -CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, - float green_mul = 1.0, float blue_mul = 1.0); +CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0f, + float green_mul = 1.0f, float blue_mul = 1.0f); CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, - float alpha = 0.2, float beta = 0.4); + float alpha = 0.2f, float beta = 0.4f); CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, double low_threshold = 30, double high_threshold = 45, int kernel_size = 3); CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, - float sigma_s = 60, float sigma_r = 0.4); + float sigma_s = 60, float sigma_r = 0.4f); CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, - float sigma_r = 0.15); + float sigma_r = 0.15f); CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, - float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); + float sigma_s = 60, float sigma_r = 0.07f, float shade_factor = 0.02f); CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, - float sigma_r = 0.45); + float sigma_r = 0.45f); } // cv diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 7794b3646d..806afdf312 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -98,7 +98,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) obj.weak_order(img,alf); // Solver - Mat Mt = Mat(polyGrad.size(),polyGrad[0].size(), CV_32FC1); + Mat Mt = Mat((int)polyGrad.size(),(int)polyGrad[0].size(), CV_32FC1); obj.wei_update_matrix(polyGrad,Cg,Mt); vector wei; diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 8a95170e32..f57dc14d32 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -117,7 +117,7 @@ void Decolor::init() kernely.at(0,0)=1.0; kernely.at(1,0)=-1.0; order = 2; - sigma = .02; + sigma = 0.02f; } vector Decolor::product(vector < vector > &comb, vector &initRGB) @@ -343,18 +343,19 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, void Decolor::wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X) { - Mat P = Mat(poly.size(),poly[0].size(), CV_32FC1); - Mat A = Mat(poly.size(),poly.size(), CV_32FC1); + int size = static_cast(poly.size()), size0 = static_cast(poly[0].size()); + Mat P = Mat(size, size0, CV_32FC1); + Mat A = Mat(size, size, CV_32FC1); - for(unsigned int i =0;i(i,j) = (float) poly[i][j]; Mat P_trans = P.t(); - Mat B = Mat(poly.size(),poly[0].size(), CV_32FC1); - for(unsigned int i =0;i < poly.size();i++) + Mat B = Mat(size, size0, CV_32FC1); + for(int i =0;i < size;i++) { - for(unsigned int j=0;j(i,j) = (float) (poly[i][j] * Cg[j]); } @@ -414,8 +415,8 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) kk=kk+1; } - float minval = INT_MAX; - float maxval = INT_MIN; + float minval = FLT_MAX; + float maxval = -FLT_MAX; for(int i=0;i Date: Fri, 6 Dec 2013 09:31:18 -0200 Subject: [PATCH 61/97] Removing ocl::oclMat::ptr() method. The method ocl::oclMat::ptr() is being removed because it returns a pointer to a row of oclMat::data. The data attribute is a cl_mem structure and cannot be iterated outside an OpenCL kernel. --- modules/ocl/doc/data_structures.rst | 8 ----- .../include/opencv2/ocl/matrix_operations.hpp | 30 ------------------- modules/ocl/include/opencv2/ocl/ocl.hpp | 8 ----- 3 files changed, 46 deletions(-) diff --git a/modules/ocl/doc/data_structures.rst b/modules/ocl/doc/data_structures.rst index 01a16739ba..bde3d14af4 100644 --- a/modules/ocl/doc/data_structures.rst +++ b/modules/ocl/doc/data_structures.rst @@ -144,14 +144,6 @@ OpenCV C++ 1-D or 2-D dense array class :: //! returns true if oclMatrix data is NULL bool empty() const; - //! returns pointer to y-th row - uchar* ptr(int y = 0); - const uchar *ptr(int y = 0) const; - - //! template version of the above method - template _Tp *ptr(int y = 0); - template const _Tp *ptr(int y = 0) const; - //! matrix transposition oclMat t() const; diff --git a/modules/ocl/include/opencv2/ocl/matrix_operations.hpp b/modules/ocl/include/opencv2/ocl/matrix_operations.hpp index ad3a16755f..e234a45aa1 100644 --- a/modules/ocl/include/opencv2/ocl/matrix_operations.hpp +++ b/modules/ocl/include/opencv2/ocl/matrix_operations.hpp @@ -456,36 +456,6 @@ namespace cv return data == 0; } - - - inline uchar *oclMat::ptr(int y) - { - CV_DbgAssert( (unsigned)y < (unsigned)rows ); - CV_Error(CV_GpuNotSupported, "This function hasn't been supported yet.\n"); - return data + step * y; - } - - inline const uchar *oclMat::ptr(int y) const - { - CV_DbgAssert( (unsigned)y < (unsigned)rows ); - CV_Error(CV_GpuNotSupported, "This function hasn't been supported yet.\n"); - return data + step * y; - } - - template inline _Tp *oclMat::ptr(int y) - { - CV_DbgAssert( (unsigned)y < (unsigned)rows ); - CV_Error(CV_GpuNotSupported, "This function hasn't been supported yet.\n"); - return (_Tp *)(data + step * y); - } - - template inline const _Tp *oclMat::ptr(int y) const - { - CV_DbgAssert( (unsigned)y < (unsigned)rows ); - CV_Error(CV_GpuNotSupported, "This function hasn't been supported yet.\n"); - return (const _Tp *)(data + step * y); - } - inline oclMat oclMat::t() const { oclMat tmp; diff --git a/modules/ocl/include/opencv2/ocl/ocl.hpp b/modules/ocl/include/opencv2/ocl/ocl.hpp index b8c9b85354..eb310a26e7 100644 --- a/modules/ocl/include/opencv2/ocl/ocl.hpp +++ b/modules/ocl/include/opencv2/ocl/ocl.hpp @@ -379,14 +379,6 @@ namespace cv //! returns true if oclMatrix data is NULL bool empty() const; - //! returns pointer to y-th row - uchar* ptr(int y = 0); - const uchar *ptr(int y = 0) const; - - //! template version of the above method - template _Tp *ptr(int y = 0); - template const _Tp *ptr(int y = 0) const; - //! matrix transposition oclMat t() const; From f5a01f15a59c06989801bd2e5a5aeab6f25bbdc2 Mon Sep 17 00:00:00 2001 From: Elena Gvozdeva Date: Fri, 6 Dec 2013 15:53:00 +0400 Subject: [PATCH 62/97] Fixed test for ocl_flip --- modules/core/test/ocl/test_arithm.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/core/test/ocl/test_arithm.cpp b/modules/core/test/ocl/test_arithm.cpp index 4755e69c24..844be7bdf2 100644 --- a/modules/core/test/ocl/test_arithm.cpp +++ b/modules/core/test/ocl/test_arithm.cpp @@ -976,7 +976,7 @@ OCL_TEST_P(Flip, X) OCL_OFF(cv::flip(src1_roi, dst1_roi, 0)); OCL_ON(cv::flip(usrc1_roi, udst1_roi, 0)); - Near(1e-5); + Near(0); } } @@ -988,7 +988,7 @@ OCL_TEST_P(Flip, Y) OCL_OFF(cv::flip(src1_roi, dst1_roi, 1)); OCL_ON(cv::flip(usrc1_roi, udst1_roi, 1)); - Near(1e-5); + Near(0); } } @@ -1000,7 +1000,7 @@ OCL_TEST_P(Flip, BOTH) OCL_OFF(cv::flip(src1_roi, dst1_roi, -1)); OCL_ON(cv::flip(usrc1_roi, udst1_roi, -1)); - Near(1e-5); + Near(0); } } From f2cf9dd8bfb30e89b113805fb3d0be1d5667e5f3 Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Fri, 6 Dec 2013 16:21:22 +0400 Subject: [PATCH 63/97] updating version to 2.4.7.2 --- modules/core/include/opencv2/core/version.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/version.hpp b/modules/core/include/opencv2/core/version.hpp index 99241a9fa2..c5a28612d7 100644 --- a/modules/core/include/opencv2/core/version.hpp +++ b/modules/core/include/opencv2/core/version.hpp @@ -50,7 +50,7 @@ #define CV_VERSION_EPOCH 2 #define CV_VERSION_MAJOR 4 #define CV_VERSION_MINOR 7 -#define CV_VERSION_REVISION 0 +#define CV_VERSION_REVISION 2 #define CVAUX_STR_EXP(__A) #__A #define CVAUX_STR(__A) CVAUX_STR_EXP(__A) From 9f04222a75b308b8d9e6865fef8d9efc9be414e0 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 6 Dec 2013 18:01:15 +0400 Subject: [PATCH 64/97] OpenCV Manager version++. --- modules/core/include/opencv2/core/version.hpp | 2 +- .../service/engine/AndroidManifest.xml | 4 +-- platforms/android/service/readme.txt | 28 +++++++++---------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/modules/core/include/opencv2/core/version.hpp b/modules/core/include/opencv2/core/version.hpp index 99241a9fa2..c5a28612d7 100644 --- a/modules/core/include/opencv2/core/version.hpp +++ b/modules/core/include/opencv2/core/version.hpp @@ -50,7 +50,7 @@ #define CV_VERSION_EPOCH 2 #define CV_VERSION_MAJOR 4 #define CV_VERSION_MINOR 7 -#define CV_VERSION_REVISION 0 +#define CV_VERSION_REVISION 2 #define CVAUX_STR_EXP(__A) #__A #define CVAUX_STR(__A) CVAUX_STR_EXP(__A) diff --git a/platforms/android/service/engine/AndroidManifest.xml b/platforms/android/service/engine/AndroidManifest.xml index 162d31eb02..7cae6ce8a0 100644 --- a/platforms/android/service/engine/AndroidManifest.xml +++ b/platforms/android/service/engine/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="216@ANDROID_PLATFORM_VERSION_CODE@" + android:versionName="2.16" > diff --git a/platforms/android/service/readme.txt b/platforms/android/service/readme.txt index 1e757a0e5f..a280b506f0 100644 --- a/platforms/android/service/readme.txt +++ b/platforms/android/service/readme.txt @@ -14,20 +14,20 @@ manually using adb tool: .. code-block:: sh - adb install OpenCV-2.4.7-android-sdk/apk/OpenCV_2.4.7_Manager_2.14_.apk + adb install OpenCV-2.4.7.1-android-sdk/apk/OpenCV_2.4.7.1_Manager_2.15_.apk Use the table below to determine proper OpenCV Manager package for your device: -+------------------------------+--------------+----------------------------------------------------+ -| Hardware Platform | Android ver. | Package name | -+==============================+==============+====================================================+ -| armeabi-v7a (ARMv7-A + NEON) | >= 2.3 | OpenCV_2.4.7_Manager_2.14_armv7a-neon.apk | -+------------------------------+--------------+----------------------------------------------------+ -| armeabi-v7a (ARMv7-A + NEON) | = 2.2 | OpenCV_2.4.7_Manager_2.14_armv7a-neon-android8.apk | -+------------------------------+--------------+----------------------------------------------------+ -| armeabi (ARMv5, ARMv6) | >= 2.3 | OpenCV_2.4.7_Manager_2.14_armeabi.apk | -+------------------------------+--------------+----------------------------------------------------+ -| Intel x86 | >= 2.3 | OpenCV_2.4.7_Manager_2.14_x86.apk | -+------------------------------+--------------+----------------------------------------------------+ -| MIPS | >= 2.3 | OpenCV_2.4.7_Manager_2.14_mips.apk | -+------------------------------+--------------+----------------------------------------------------+ ++------------------------------+--------------+------------------------------------------------------+ +| Hardware Platform | Android ver. | Package name | ++==============================+==============+======================================================+ +| armeabi-v7a (ARMv7-A + NEON) | >= 2.3 | OpenCV_2.4.7.1_Manager_2.15_armv7a-neon.apk | ++------------------------------+--------------+------------------------------------------------------+ +| armeabi-v7a (ARMv7-A + NEON) | = 2.2 | OpenCV_2.4.7.1_Manager_2.15_armv7a-neon-android8.apk | ++------------------------------+--------------+------------------------------------------------------+ +| armeabi (ARMv5, ARMv6) | >= 2.3 | OpenCV_2.4.7.1_Manager_2.15_armeabi.apk | ++------------------------------+--------------+------------------------------------------------------+ +| Intel x86 | >= 2.3 | OpenCV_2.4.7.1_Manager_2.15_x86.apk | ++------------------------------+--------------+------------------------------------------------------+ +| MIPS | >= 2.3 | OpenCV_2.4.7.1_Manager_2.15_mips.apk | ++------------------------------+--------------+------------------------------------------------------+ From 73aa43d2cab0fabad828934d8e94d59e47722f86 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 6 Dec 2013 15:52:34 +0400 Subject: [PATCH 65/97] fixed warnings --- modules/imgproc/src/sumpixels.cpp | 11 +++++------ modules/photo/src/contrast_preserve.hpp | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/modules/imgproc/src/sumpixels.cpp b/modules/imgproc/src/sumpixels.cpp index f353945df7..2160b20575 100644 --- a/modules/imgproc/src/sumpixels.cpp +++ b/modules/imgproc/src/sumpixels.cpp @@ -250,9 +250,9 @@ static bool ocl_integral( InputArray _src, OutputArray _sum, int sdepth ) UMat src = _src.getUMat(), t_sum(t_size, sdepth), sum = _sum.getUMat(); t_sum = t_sum(Range::all(), Range(0, size.height)); - int offset = src.offset / vlen, pre_invalid = src.offset % vlen; + int offset = (int)src.offset / vlen, pre_invalid = (int)src.offset % vlen; int vcols = (pre_invalid + src.cols + vlen - 1) / vlen; - int sum_offset = sum.offset / vlen; + int sum_offset = (int)sum.offset / vlen; k1.args(ocl::KernelArg::PtrReadOnly(src), ocl::KernelArg::PtrWriteOnly(t_sum), offset, pre_invalid, src.rows, src.cols, (int)src.step, (int)t_sum.step); @@ -297,12 +297,11 @@ static bool ocl_integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, _sqsum.create(dsize, sqdepth); UMat sum = _sum.getUMat(), sqsum = _sqsum.getUMat(); - int offset = src.offset / vlen; + int offset = (int)src.offset / vlen; int pre_invalid = src.offset % vlen; int vcols = (pre_invalid + src.cols + vlen - 1) / vlen; - int sum_offset = sum.offset / sum.elemSize(); - int sqsum_offset = sqsum.offset / sqsum.elemSize(); - CV_Assert(sqsum.offset % sqsum.elemSize() == 0); + int sum_offset = (int)(sum.offset / sum.elemSize()); + int sqsum_offset = (int)(sqsum.offset / sqsum.elemSize()); k1.args(ocl::KernelArg::PtrReadOnly(src), ocl::KernelArg::PtrWriteOnly(t_sum), ocl::KernelArg::PtrWriteOnly(t_sqsum), offset, pre_invalid, src.rows, diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index f57dc14d32..0cc6bce850 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -355,7 +355,7 @@ void Decolor::wei_update_matrix(vector < vector > &poly, vector (i,j) = (float) (poly[i][j] * Cg[j]); } From 0eb2be762a77d119e4bda7f90a7074c6032e5052 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 5 Dec 2013 03:23:52 +0400 Subject: [PATCH 66/97] cmake: allow source_group to preserve file-system tree (for MSVS) --- cmake/OpenCVModule.cmake | 21 ++++++++-------- cmake/OpenCVUtils.cmake | 53 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 14 deletions(-) diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 011529d651..c445e3fe59 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -485,6 +485,9 @@ macro(ocv_glob_module_sources) file(GLOB lib_hdrs "include/opencv2/*.hpp" "include/opencv2/${name}/*.hpp" "include/opencv2/${name}/*.h") file(GLOB lib_hdrs_detail "include/opencv2/${name}/detail/*.hpp" "include/opencv2/${name}/detail/*.h") + ocv_source_group("Src" DIRBASE "${CMAKE_CURRENT_SOURCE_DIR}/src" FILES ${lib_srcs} ${lib_int_hdrs}) + ocv_source_group("Include" DIRBASE "${CMAKE_CURRENT_SOURCE_DIR}/include" FILES ${lib_hdrs} ${lib_hdrs_detail}) + file(GLOB lib_cuda_srcs "src/cuda/*.cu") set(cuda_objs "") set(lib_cuda_hdrs "") @@ -493,11 +496,9 @@ macro(ocv_glob_module_sources) file(GLOB lib_cuda_hdrs "src/cuda/*.hpp") ocv_cuda_compile(cuda_objs ${lib_cuda_srcs} ${lib_cuda_hdrs}) - source_group("Src\\Cuda" FILES ${lib_cuda_srcs} ${lib_cuda_hdrs}) + source_group("Src\\Cuda" FILES ${lib_cuda_srcs} ${lib_cuda_hdrs}) endif() - source_group("Src" FILES ${lib_srcs} ${lib_int_hdrs}) - file(GLOB cl_kernels "src/opencl/*.cl") if(cl_kernels) ocv_include_directories(${OPENCL_INCLUDE_DIRS}) @@ -506,15 +507,13 @@ macro(ocv_glob_module_sources) OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.hpp" COMMAND ${CMAKE_COMMAND} -DMODULE_NAME="${the_module_barename}" -DCL_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src/opencl" -DOUTPUT="${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" -P "${OpenCV_SOURCE_DIR}/cmake/cl2cpp.cmake" DEPENDS ${cl_kernels} "${OpenCV_SOURCE_DIR}/cmake/cl2cpp.cmake") - source_group("OpenCL" FILES ${cl_kernels} "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.hpp") + ocv_source_group("Src\\opencl\\kernels" FILES ${cl_kernels}) + ocv_source_group("Src\\opencl\\kernels\\autogenerated" FILES "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.hpp") list(APPEND lib_srcs ${cl_kernels} "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.hpp") endif() ocv_set_module_sources(${ARGN} HEADERS ${lib_hdrs} ${lib_hdrs_detail} SOURCES ${lib_srcs} ${lib_int_hdrs} ${cuda_objs} ${lib_cuda_srcs} ${lib_cuda_hdrs}) - - source_group("Include" FILES ${lib_hdrs}) - source_group("Include\\detail" FILES ${lib_hdrs_detail}) endmacro() # creates OpenCV module in current folder @@ -692,8 +691,8 @@ function(ocv_add_perf_tests) if(NOT OPENCV_PERF_${the_module}_SOURCES) file(GLOB_RECURSE perf_srcs "${perf_path}/*.cpp") file(GLOB_RECURSE perf_hdrs "${perf_path}/*.hpp" "${perf_path}/*.h") - source_group("Src" FILES ${perf_srcs}) - source_group("Include" FILES ${perf_hdrs}) + ocv_source_group("Src" DIRBASE "${perf_path}" FILES ${perf_srcs}) + ocv_source_group("Include" DIRBASE "${perf_path}" FILES ${perf_hdrs}) set(OPENCV_PERF_${the_module}_SOURCES ${perf_srcs} ${perf_hdrs}) endif() @@ -742,8 +741,8 @@ function(ocv_add_accuracy_tests) if(NOT OPENCV_TEST_${the_module}_SOURCES) file(GLOB_RECURSE test_srcs "${test_path}/*.cpp") file(GLOB_RECURSE test_hdrs "${test_path}/*.hpp" "${test_path}/*.h") - source_group("Src" FILES ${test_srcs}) - source_group("Include" FILES ${test_hdrs}) + ocv_source_group("Src" DIRBASE "${test_path}" FILES ${test_srcs}) + ocv_source_group("Include" DIRBASE "${test_path}" FILES ${test_hdrs}) set(OPENCV_TEST_${the_module}_SOURCES ${test_srcs} ${test_hdrs}) endif() diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index 13461e82c1..677d7f5d5c 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -1,3 +1,22 @@ +# Debugging function +function(ocv_cmake_dump_vars) + cmake_parse_arguments(DUMP "" "TOFILE" "" ${ARGN}) + set(regex "${DUMP_UNPARSED_ARGUMENTS}") + get_cmake_property(_variableNames VARIABLES) + set(VARS "") + foreach(_variableName ${_variableNames}) + if(_variableName MATCHES "${regex}") + set(VARS "${VARS}${_variableName}=${${_variableName}}\n") + endif() + endforeach() + if(DUMP_TOFILE) + file(WRITE ${CMAKE_BINARY_DIR}/${DUMP_TOFILE} "${VARS}") + else() + message(AUTHOR_WARNING "${VARS}") + endif() +endfunction() + + # Search packages for host system instead of packages for target system # in case of cross compilation thess macro should be defined by toolchain file if(NOT COMMAND find_host_package) @@ -601,7 +620,35 @@ endmacro() ################################################################################################ # short command to setup source group 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}) + cmake_parse_arguments(SG "" "DIRBASE" "GLOB;GLOB_RECURSE;FILES" ${ARGN}) + set(files "") + if(SG_FILES) + list(APPEND files ${SG_FILES}) + endif() + if(SG_GLOB) + file(GLOB srcs ${SG_GLOB}) + list(APPEND files ${srcs}) + endif() + if(SG_GLOB_RECURSE) + file(GLOB_RECURSE srcs ${SG_GLOB_RECURSE}) + list(APPEND files ${srcs}) + endif() + if(SG_DIRBASE) + foreach(f ${files}) + file(RELATIVE_PATH fpart "${SG_DIRBASE}" "${f}") + if(fpart MATCHES "^\\.\\.") + message(AUTHOR_WARNING "Can't detect subpath for source_group command: Group=${group} FILE=${f} DIRBASE=${SG_DIRBASE}") + set(fpart "") + else() + get_filename_component(fpart "${fpart}" PATH) + if(fpart) + set(fpart "/${fpart}") # add '/' + string(REPLACE "/" "\\" fpart "${fpart}") + endif() + endif() + source_group("${group}${fpart}" FILES ${f}) + endforeach() + else() + source_group(${group} FILES ${files}) + endif() endfunction() From b560cc35d9cd1290b4e9fff66a1b478042fd9a79 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Mon, 18 Nov 2013 14:38:12 +0400 Subject: [PATCH 67/97] removed Ptr typedef from Viz3d. It is deprecated since Viz3d itseez is a shared pointer --- modules/viz/include/opencv2/viz/viz3d.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index b121472741..59654b5c93 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -64,7 +64,6 @@ namespace cv class CV_EXPORTS Viz3d { public: - typedef cv::Ptr Ptr; typedef void (*KeyboardCallback)(const KeyboardEvent&, void*); typedef void (*MouseCallback)(const MouseEvent&, void*); From 0895616576a722cf8d0b5762cc600aabcb2cb072 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Mon, 18 Nov 2013 14:50:05 +0400 Subject: [PATCH 68/97] switched from unnecessarily 'dobule' to 'float' in some places (commonly for widget scale) --- modules/viz/doc/widget.rst | 64 ++++++++++----------- modules/viz/include/opencv2/viz/widgets.hpp | 34 +++++------ modules/viz/src/shape_widgets.cpp | 32 +++++------ 3 files changed, 65 insertions(+), 65 deletions(-) diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 6ceccf0cb9..bbbfef63a9 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -262,8 +262,8 @@ This 3D Widget defines a finite plane. :: class CV_EXPORTS WPlane : public Widget3D { public: - WPlane(const Vec4f& coefs, double size = 1.0, const Color &color = Color::white()); - WPlane(const Vec4f& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()); + WPlane(const Vec4f& coefs, float size = 1.0, const Color &color = Color::white()); + WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.0, const Color &color = Color::white()); private: /* hidden */ }; @@ -272,13 +272,13 @@ viz::WPlane::WPlane ------------------- Constructs a WPlane. -.. ocv:function:: WPlane(const Vec4f& coefs, double size = 1.0, const Color &color = Color::white()) +.. ocv:function:: WPlane(const Vec4f& coefs, float size = 1.0, const Color &color = Color::white()) :param coefs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. :param size: Size of the plane. :param color: :ocv:class:`Color` of the plane. -.. ocv:function:: WPlane(const Vec4f& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()) +.. ocv:function:: WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.0, const Color &color = Color::white()) :param coefs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0. :param pt: Position of the plane. @@ -317,14 +317,14 @@ This 3D Widget defines an arrow. :: class CV_EXPORTS WArrow : public Widget3D { public: - WArrow(const Point3f& pt1, const Point3f& pt2, double thickness = 0.03, const Color &color = Color::white()); + WArrow(const Point3f& pt1, const Point3f& pt2, float thickness = 0.03, const Color &color = Color::white()); }; viz::WArrow::WArrow ----------------------------- Constructs an WArrow. -.. ocv:function:: WArrow(const Point3f& pt1, const Point3f& pt2, double thickness = 0.03, const Color &color = Color::white()) +.. ocv:function:: WArrow(const Point3f& pt1, const Point3f& pt2, float thickness = 0.03, const Color &color = Color::white()) :param pt1: Start point of the arrow. :param pt2: End point of the arrow. @@ -342,14 +342,14 @@ This 3D Widget defines a circle. :: class CV_EXPORTS WCircle : public Widget3D { public: - WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white()); + WCircle(const Point3f& pt, float radius, float thickness = 0.01, const Color &color = Color::white()); }; viz::WCircle::WCircle ------------------------------- Constructs a WCircle. -.. ocv:function:: WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white()) +.. ocv:function:: WCircle(const Point3f& pt, float radius, float thickness = 0.01, const Color &color = Color::white()) :param pt: Center of the circle. :param radius: Radius of the circle. @@ -365,14 +365,14 @@ This 3D Widget defines a cylinder. :: class CV_EXPORTS WCylinder : public Widget3D { public: - WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()); + WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides = 30, const Color &color = Color::white()); }; viz::WCylinder::WCylinder ----------------------------------- Constructs a WCylinder. -.. ocv:function:: WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()) +.. ocv:function:: WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides = 30, const Color &color = Color::white()) :param pt_on_axis: A point on the axis of the cylinder. :param axis_direction: Direction of the axis of the cylinder. @@ -416,14 +416,14 @@ This 3D Widget represents a coordinate system. :: class CV_EXPORTS WCoordinateSystem : public Widget3D { public: - WCoordinateSystem(double scale = 1.0); + WCoordinateSystem(float scale = 1.0); }; viz::WCoordinateSystem::WCoordinateSystem --------------------------------------------------- Constructs a WCoordinateSystem. -.. ocv:function:: WCoordinateSystem(double scale = 1.0) +.. ocv:function:: WCoordinateSystem(float scale = 1.0) :param scale: Determines the size of the axes. @@ -494,7 +494,7 @@ This 3D Widget represents 3D text. The text always faces the camera. :: class CV_EXPORTS WText3D : public Widget3D { public: - WText3D(const String &text, const Point3f &position, double text_scale = 1.0, double face_camera = true, const Color &color = Color::white()); + WText3D(const String &text, const Point3f &position, float text_scale = 1.0, bool face_camera = true, const Color &color = Color::white()); void setText(const String &text); String getText() const; @@ -504,7 +504,7 @@ viz::WText3D::WText3D ------------------------------- Constructs a WText3D. -.. ocv:function:: WText3D(const String &text, const Point3f &position, double text_scale = 1.0, double face_camera = true, const Color &color = Color::white()) +.. ocv:function:: WText3D(const String &text, const Point3f &position, float text_scale = 1.0, bool face_camera = true, const Color &color = Color::white()) :param text: Text content of the widget. :param position: Position of the text. @@ -649,15 +649,15 @@ This 3D Widget represents camera position in a scene by its axes or viewing frus { public: //! Creates camera coordinate frame (axes) at the origin - WCameraPosition(double scale = 1.0); + WCameraPosition(float scale = 1.0); //! Creates frustum based on the intrinsic marix K at the origin - WCameraPosition(const Matx33f &K, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); //! Creates frustum based on the field of view at the origin - WCameraPosition(const Vec2f &fov, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Matx33f &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.0, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Vec2f &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.0, const Color &color = Color::white()); }; viz::WCameraPosition::WCameraPosition @@ -666,7 +666,7 @@ Constructs a WCameraPosition. - **Display camera coordinate frame.** - .. ocv:function:: WCameraPosition(double scale = 1.0) + .. ocv:function:: WCameraPosition(float scale = 1.0) Creates camera coordinate frame at the origin. @@ -676,7 +676,7 @@ Constructs a WCameraPosition. - **Display the viewing frustum.** - .. ocv:function:: WCameraPosition(const Matx33f &K, double scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) :param K: Intrinsic matrix of the camera. :param scale: Scale of the frustum. @@ -684,7 +684,7 @@ Constructs a WCameraPosition. Creates viewing frustum of the camera based on its intrinsic matrix K. - .. ocv:function:: WCameraPosition(const Vec2f &fov, double scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) :param fov: Field of view of the camera (horizontal, vertical). :param scale: Scale of the frustum. @@ -698,7 +698,7 @@ Constructs a WCameraPosition. - **Display image on the far plane of the viewing frustum.** - .. ocv:function:: WCameraPosition(const Matx33f &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.0, const Color &color = Color::white()) :param K: Intrinsic matrix of the camera. :param img: BGR or Gray-Scale image that is going to be displayed on the far plane of the frustum. @@ -707,7 +707,7 @@ Constructs a WCameraPosition. Creates viewing frustum of the camera based on its intrinsic matrix K, and displays image on the far end plane. - .. ocv:function:: WCameraPosition(const Vec2f &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()) + .. ocv:function:: WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.0, const Color &color = Color::white()) :param fov: Field of view of the camera (horizontal, vertical). :param img: BGR or Gray-Scale image that is going to be displayed on the far plane of the frustum. @@ -732,11 +732,11 @@ This 3D Widget represents a trajectory. :: enum {DISPLAY_FRAMES = 1, DISPLAY_PATH = 2}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), double scale = 1.0); + WTrajectory(const std::vector &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.0); //! Displays trajectory of the given path by frustums - WTrajectory(const std::vector &path, const Matx33f &K, double scale = 1.0, const Color &color = Color::white()); + WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectory(const std::vector &path, const Vec2f &fov, double scale = 1.0, const Color &color = Color::white()); + WTrajectory(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()); private: /* hidden */ @@ -746,7 +746,7 @@ viz::WTrajectory::WTrajectory ----------------------------- Constructs a WTrajectory. -.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), double scale = 1.0) +.. ocv:function:: WTrajectory(const std::vector &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.0) :param path: List of poses on a trajectory. :param display_mode: Display mode. This can be DISPLAY_PATH, DISPLAY_FRAMES, DISPLAY_PATH & DISPLAY_FRAMES. @@ -759,7 +759,7 @@ Constructs a WTrajectory. * DISPLAY_FRAMES : Displays coordinate frames at each pose. * DISPLAY_PATH & DISPLAY_FRAMES : Displays both poly line and coordinate frames. -.. ocv:function:: WTrajectory(const std::vector &path, const Matx33f &K, double scale = 1.0, const Color &color = Color::white()) +.. ocv:function:: WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param K: Intrinsic matrix of the camera. @@ -768,7 +768,7 @@ Constructs a WTrajectory. Displays frustums at each pose of the trajectory. -.. ocv:function:: WTrajectory(const std::vector &path, const Vec2f &fov, double scale = 1.0, const Color &color = Color::white()) +.. ocv:function:: WTrajectory(const std::vector &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white()) :param path: List of poses on a trajectory. :param fov: Field of view of the camera (horizontal, vertical). @@ -788,7 +788,7 @@ represent the direction from previous position to the current. :: { public: WSpheresTrajectory(const std::vector &path, float line_length = 0.05f, - double init_sphere_radius = 0.021, sphere_radius = 0.007, + float init_sphere_radius = 0.021, sphere_radius = 0.007, Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; @@ -796,7 +796,7 @@ viz::WSpheresTrajectory::WSpheresTrajectory ------------------------------------------- Constructs a WSpheresTrajectory. -.. ocv:function:: WSpheresTrajectory(const std::vector &path, float line_length = 0.05f, double init_sphere_radius = 0.021, double sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) +.. ocv:function:: WSpheresTrajectory(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021, float sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()) :param path: List of poses on a trajectory. :param line_length: Length of the lines. diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 9a2c5ecbf8..07b3358993 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -143,8 +143,8 @@ namespace cv class CV_EXPORTS WPlane : public Widget3D { public: - WPlane(const Vec4f& coefs, double size = 1.0, const Color &color = Color::white()); - WPlane(const Vec4f& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white()); + WPlane(const Vec4f& coefs, float size = 1.f, const Color &color = Color::white()); + WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.f, const Color &color = Color::white()); private: struct SetSizeImpl; }; @@ -158,19 +158,19 @@ namespace cv class CV_EXPORTS WArrow : public Widget3D { public: - WArrow(const Point3f& pt1, const Point3f& pt2, double thickness = 0.03, const Color &color = Color::white()); + WArrow(const Point3f& pt1, const Point3f& pt2, float thickness = 0.03f, const Color &color = Color::white()); }; class CV_EXPORTS WCircle : public Widget3D { public: - WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white()); + WCircle(const Point3f& pt, float radius, float thickness = 0.01f, const Color &color = Color::white()); }; class CV_EXPORTS WCylinder : public Widget3D { public: - WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white()); + WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides = 30, const Color &color = Color::white()); }; class CV_EXPORTS WCube : public Widget3D @@ -182,7 +182,7 @@ namespace cv class CV_EXPORTS WCoordinateSystem : public Widget3D { public: - WCoordinateSystem(double scale = 1.0); + WCoordinateSystem(float scale = 1.f); }; class CV_EXPORTS WPolyLine : public Widget3D @@ -210,7 +210,7 @@ namespace cv class CV_EXPORTS WText3D : public Widget3D { public: - WText3D(const String &text, const Point3f &position, double text_scale = 1.0, bool face_camera = true, const Color &color = Color::white()); + WText3D(const String &text, const Point3f &position, float text_scale = 1.f, bool face_camera = true, const Color &color = Color::white()); void setText(const String &text); String getText() const; @@ -248,15 +248,15 @@ namespace cv { public: //! Creates camera coordinate frame (axes) at the origin - WCameraPosition(double scale = 1.0); + WCameraPosition(float scale = 1.f); //! Creates frustum based on the intrinsic marix K at the origin - WCameraPosition(const Matx33f &K, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum based on the field of view at the origin - WCameraPosition(const Vec2f &fov, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Matx33f &K, const Mat &img, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white()); //! Creates frustum and display given image at the far plane - WCameraPosition(const Vec2f &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white()); + WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white()); private: struct ProjectImage; @@ -268,11 +268,11 @@ namespace cv enum {DISPLAY_FRAMES = 1, DISPLAY_PATH = 2}; //! Displays trajectory of the given path either by coordinate frames or polyline - WTrajectory(const std::vector &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), double scale = 1.0); + WTrajectory(const std::vector &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.f); //! Displays trajectory of the given path by frustums - WTrajectory(const std::vector &path, const Matx33f &K, double scale = 1.0, const Color &color = Color::white()); + WTrajectory(const std::vector &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white()); //! Displays trajectory of the given path by frustums - WTrajectory(const std::vector &path, const Vec2f &fov, double scale = 1.0, const Color &color = Color::white()); + WTrajectory(const std::vector &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white()); private: struct ApplyPath; @@ -281,8 +281,8 @@ namespace cv class CV_EXPORTS WSpheresTrajectory: public Widget3D { public: - WSpheresTrajectory(const std::vector &path, float line_length = 0.05f, double init_sphere_radius = 0.021, - double sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); + WSpheresTrajectory(const std::vector &path, float line_length = 0.05f, float init_sphere_radius = 0.021f, + float sphere_radius = 0.007f, const Color &line_color = Color::white(), const Color &sphere_color = Color::white()); }; class CV_EXPORTS WCloud: public Widget3D diff --git a/modules/viz/src/shape_widgets.cpp b/modules/viz/src/shape_widgets.cpp index 2e062d52d5..6e4f4c70ff 100644 --- a/modules/viz/src/shape_widgets.cpp +++ b/modules/viz/src/shape_widgets.cpp @@ -104,7 +104,7 @@ struct cv::viz::WPlane::SetSizeImpl } }; -cv::viz::WPlane::WPlane(const Vec4f& coefs, double size, const Color &color) +cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color) { vtkSmartPointer plane = vtkSmartPointer::New(); plane->SetNormal(coefs[0], coefs[1], coefs[2]); @@ -124,7 +124,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, double size, const Color &color) setColor(color); } -cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, double size, const Color &color) +cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, float size, const Color &color) { vtkSmartPointer plane = vtkSmartPointer::New(); Point3f coefs3(coefs[0], coefs[1], coefs[2]); @@ -183,7 +183,7 @@ template<> cv::viz::WSphere cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// arrow widget implementation -cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, double thickness, const Color &color) +cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, const Color &color) { vtkSmartPointer arrowSource = vtkSmartPointer::New(); arrowSource->SetShaftRadius(thickness); @@ -256,7 +256,7 @@ template<> cv::viz::WArrow cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// circle widget implementation -cv::viz::WCircle::WCircle(const Point3f& pt, double radius, double thickness, const Color& color) +cv::viz::WCircle::WCircle(const Point3f& pt, float radius, float thickness, const Color& color) { vtkSmartPointer disk = vtkSmartPointer::New(); // Maybe the resolution should be lower e.g. 50 or 25 @@ -292,7 +292,7 @@ template<> cv::viz::WCircle cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// cylinder widget implementation -cv::viz::WCylinder::WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides, const Color &color) +cv::viz::WCylinder::WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides, const Color &color) { const Point3f pt2 = pt_on_axis + axis_direction; vtkSmartPointer line = vtkSmartPointer::New(); @@ -355,7 +355,7 @@ template<> cv::viz::WCube cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// coordinate system widget implementation -cv::viz::WCoordinateSystem::WCoordinateSystem(double scale) +cv::viz::WCoordinateSystem::WCoordinateSystem(float scale) { vtkSmartPointer axes = vtkSmartPointer::New(); axes->SetOrigin(0, 0, 0); @@ -593,7 +593,7 @@ template<> cv::viz::WGrid cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// text3D widget implementation -cv::viz::WText3D::WText3D(const String &text, const Point3f &position, double text_scale, bool face_camera, const Color &color) +cv::viz::WText3D::WText3D(const String &text, const Point3f &position, float text_scale, bool face_camera, const Color &color) { vtkSmartPointer textSource = vtkSmartPointer::New(); textSource->SetText(text.c_str()); @@ -1032,7 +1032,7 @@ struct cv::viz::WCameraPosition::ProjectImage } }; -cv::viz::WCameraPosition::WCameraPosition(double scale) +cv::viz::WCameraPosition::WCameraPosition(float scale) { vtkSmartPointer axes = vtkSmartPointer::New(); axes->SetOrigin(0, 0, 0); @@ -1074,7 +1074,7 @@ cv::viz::WCameraPosition::WCameraPosition(double scale) WidgetAccessor::setProp(*this, actor); } -cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, double scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, float scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); float f_x = K(0,0); @@ -1116,7 +1116,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, double scale, const } -cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, double scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, float scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); @@ -1154,7 +1154,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, double scale, const setColor(color); } -cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, const Mat &image, double scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, const Mat &image, float scale, const Color &color) { CV_Assert(!image.empty() && image.depth() == CV_8U); float f_y = K(1,1); @@ -1168,7 +1168,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, const Mat &image, do WidgetAccessor::setProp(*this, actor); } -cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, const Mat &image, double scale, const Color &color) +cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, const Mat &image, float scale, const Color &color) { CV_Assert(!image.empty() && image.depth() == CV_8U); float fovy = fov[1] * 180.0f / CV_PI; @@ -1220,7 +1220,7 @@ struct cv::viz::WTrajectory::ApplyPath } }; -cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, const Color &color, double scale) +cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display_mode, const Color &color, float scale) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); @@ -1316,7 +1316,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, int display WidgetAccessor::setProp(*this, actor); } -cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Matx33f &K, double scale, const Color &color) +cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Matx33f &K, float scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); float f_x = K(0,0); @@ -1360,7 +1360,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Matx3 setColor(color); } -cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Vec2f &fov, double scale, const Color &color) +cv::viz::WTrajectory::WTrajectory(const std::vector &path, const Vec2f &fov, float scale, const Color &color) { vtkSmartPointer camera = vtkSmartPointer::New(); @@ -1409,7 +1409,7 @@ template<> cv::viz::WTrajectory cv::viz::Widget::cast() /////////////////////////////////////////////////////////////////////////////////////////////// /// spheres trajectory widget implementation -cv::viz::WSpheresTrajectory::WSpheresTrajectory(const std::vector &path, float line_length, double init_sphere_radius, double sphere_radius, +cv::viz::WSpheresTrajectory::WSpheresTrajectory(const std::vector &path, float line_length, float init_sphere_radius, float sphere_radius, const Color &line_color, const Color &sphere_color) { vtkSmartPointer appendFilter = vtkSmartPointer::New(); From 177f7eb339538b66f0e0c6c1dab63899471c26fc Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 19 Nov 2013 12:14:24 +0400 Subject: [PATCH 69/97] fixed warning --- modules/viz/src/viz3d_impl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/viz/src/viz3d_impl.cpp b/modules/viz/src/viz3d_impl.cpp index ae8fc150c6..14107c5d1e 100644 --- a/modules/viz/src/viz3d_impl.cpp +++ b/modules/viz/src/viz3d_impl.cpp @@ -568,7 +568,7 @@ void cv::viz::Viz3d::VizImpl::updateCells(vtkSmartPointer &cells cells->SetNumberOfTuples(nr_points); vtkIdType *cell = cells->GetPointer(0); // Fill it with 1s - std::fill_n(cell, nr_points * 2, 1); + std::fill(cell, cell + nr_points * 2, 1); cell++; for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) *cell = i; From a9c7aa92d9fbe4a2cf4f63b1394eb67c978a69bb Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 19 Nov 2013 12:39:19 +0400 Subject: [PATCH 70/97] removed CV_EXPORTS from cv::Afiine --- modules/core/include/opencv2/core/affine.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index ed8bd29a18..cadc7ee26f 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -51,7 +51,7 @@ namespace cv { template - class CV_EXPORTS Affine3 + class Affine3 { public: typedef T float_type; From 9f1f5aed53b499998b0149f757d0711734b6c029 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 22 Nov 2013 14:12:33 +0400 Subject: [PATCH 71/97] compilation --- modules/core/include/opencv2/core/operations.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/operations.hpp b/modules/core/include/opencv2/core/operations.hpp index f8aeddfb11..ac62dc8270 100644 --- a/modules/core/include/opencv2/core/operations.hpp +++ b/modules/core/include/opencv2/core/operations.hpp @@ -435,7 +435,7 @@ int print(const std::vector >& vec, FILE* stream = stdout) template static inline int print(const Matx<_Tp, m, n>& matx, FILE* stream = stdout) { - return print(Formatter::get()->format(matx), stream); + return print(Formatter::get()->format(cv::Mat(matx)), stream); } From ace71cef3f635517a17e9e8f2091e8e3d3ff267a Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 21 Nov 2013 21:20:20 +0400 Subject: [PATCH 72/97] Added Affine3::rvec() --- modules/core/include/opencv2/core/affine.hpp | 52 ++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index cadc7ee26f..fa7eed8638 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -97,6 +97,9 @@ namespace cv Mat3 linear() const; Vec3 translation() const; + //Rodrigues vector + Vec3 rvec() const; + Affine3 inv(int method = cv::DECOMP_SVD) const; // a.rotate(R) is equivalent to Affine(R, 0) * a; @@ -300,6 +303,55 @@ typename cv::Affine3::Vec3 cv::Affine3::translation() const return Vec3(matrix.val[3], matrix.val[7], matrix.val[11]); } +template inline +typename cv::Affine3::Vec3 cv::Affine3::rvec() const +{ + cv::Vec3d w; + cv::Matx33d u, vt, R = rotation(); + cv::SVD::compute(R, w, u, vt, cv::SVD::FULL_UV + cv::SVD::MODIFY_A); + R = u * vt; + + double rx = R.val[7] - R.val[5]; + double ry = R.val[2] - R.val[6]; + double rz = R.val[3] - R.val[1]; + + double s = std::sqrt((rx*rx + ry*ry + rz*rz)*0.25); + double c = (R.val[0] + R.val[4] + R.val[8] - 1) * 0.5; + c = c > 1.0 ? 1.0 : c < -1.0 ? -1.0 : c; + double theta = acos(c); + + if( s < 1e-5 ) + { + if( c > 0 ) + rx = ry = rz = 0; + else + { + double t; + t = (R.val[0] + 1) * 0.5; + rx = std::sqrt(std::max(t, 0.0)); + t = (R.val[4] + 1) * 0.5; + ry = std::sqrt(std::max(t, 0.0)) * (R.val[1] < 0 ? -1.0 : 1.0); + t = (R.val[8] + 1) * 0.5; + rz = std::sqrt(std::max(t, 0.0)) * (R.val[2] < 0 ? -1.0 : 1.0); + + if( fabs(rx) < fabs(ry) && fabs(rx) < fabs(rz) && (R.val[5] > 0) != (ry*rz > 0) ) + rz = -rz; + theta /= std::sqrt(rx*rx + ry*ry + rz*rz); + rx *= theta; + ry *= theta; + rz *= theta; + } + } + else + { + double vth = 1/(2*s); + vth *= theta; + rx *= vth; ry *= vth; rz *= vth; + } + + return cv::Vec3d(rx, ry, rz); +} + template inline cv::Affine3 cv::Affine3::inv(int method) const { From d970d58308b3e70c498c01c99c5068f06d1240e1 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 24 Nov 2013 18:15:37 +0400 Subject: [PATCH 73/97] added Viz::tutorial2 test --- modules/viz/test/test_tutorial2.cpp | 54 +++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 modules/viz/test/test_tutorial2.cpp diff --git a/modules/viz/test/test_tutorial2.cpp b/modules/viz/test/test_tutorial2.cpp new file mode 100644 index 0000000000..6e9189b8f2 --- /dev/null +++ b/modules/viz/test/test_tutorial2.cpp @@ -0,0 +1,54 @@ +#include "test_precomp.hpp" + +using namespace cv; +using namespace std; + +void tutorial2() +{ + /// Create a window + viz::Viz3d myWindow("Coordinate Frame"); + + /// Add coordinate axes + myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem()); + + /// Add line to represent (1,1,1) axis + viz::WLine axis(Point3f(-1.0f,-1.0f,-1.0f), Point3f(1.0f,1.0f,1.0f)); + axis.setRenderingProperty(viz::LINE_WIDTH, 4.0); + myWindow.showWidget("Line Widget", axis); + + /// Construct a cube widget + viz::WCube cube_widget(Point3f(0.5,0.5,0.0), Point3f(0.0,0.0,-0.5), true, viz::Color::blue()); + cube_widget.setRenderingProperty(viz::LINE_WIDTH, 4.0); + + /// Display widget (update if already displayed) + myWindow.showWidget("Cube Widget", cube_widget); + + /// Rodrigues vector + Mat rot_vec = Mat::zeros(1,3,CV_32F); + float translation_phase = 0.0, translation = 0.0; + while(!myWindow.wasStopped()) + { + /* Rotation using rodrigues */ + /// Rotate around (1,1,1) + rot_vec.at(0,0) += CV_PI * 0.01f; + rot_vec.at(0,1) += CV_PI * 0.01f; + rot_vec.at(0,2) += CV_PI * 0.01f; + + /// Shift on (1,1,1) + translation_phase += CV_PI * 0.01f; + translation = sin(translation_phase); + + /// Construct pose + Affine3f pose(rot_vec, Vec3f(translation, translation, translation)); + + myWindow.setWidgetPose("Cube Widget", pose); + + myWindow.spinOnce(1, true); + } +} + + +TEST(Viz_viz3d, DISABLED_tutorial2_pose_of_widget) +{ + tutorial2(); +} From b88fdc73d65132c237acfab49c08e3884980eac8 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 24 Nov 2013 20:06:32 +0400 Subject: [PATCH 74/97] VizAccessor is now private and renamed to VizStorage --- modules/viz/include/opencv2/viz.hpp | 31 ++------- modules/viz/include/opencv2/viz/viz3d.hpp | 2 + modules/viz/src/precomp.hpp | 33 ++++++--- modules/viz/src/viz.cpp | 82 ++++++++--------------- modules/viz/src/viz3d.cpp | 33 +++++---- 5 files changed, 78 insertions(+), 103 deletions(-) diff --git a/modules/viz/include/opencv2/viz.hpp b/modules/viz/include/opencv2/viz.hpp index 5c2fe03d93..d4f08af725 100644 --- a/modules/viz/include/opencv2/viz.hpp +++ b/modules/viz/include/opencv2/viz.hpp @@ -63,9 +63,12 @@ namespace cv //! constructs camera pose from position, focal_point and up_vector (see gluLookAt() for more infromation) CV_EXPORTS Affine3f makeCameraPose(const Vec3f& position, const Vec3f& focal_point, const Vec3f& y_dir); - //! retrieves a window by its name + //! retrieves a window by its name. If no window with such name, then it creates new. CV_EXPORTS Viz3d get(const String &window_name); + //! Unregisters all Viz windows from internal database. After it 'get()' will create new windows instead getting existing from the database. + CV_EXPORTS void unregisterAllWindows(); + //! checks float value for Nan inline bool isNan(float x) { @@ -88,32 +91,6 @@ namespace cv template inline bool isNan(const Point3_<_Tp>& p) { return isNan(p.x) || isNan(p.y) || isNan(p.z); } - //! helper class that provides access by name infrastructure - class CV_EXPORTS VizAccessor - { - public: - static VizAccessor & getInstance(); - static void release(); - - Viz3d get(const String &window_name); - - //! window names automatically have Viz - prefix even though not provided by the users - static void generateWindowName(const String &window_name, String &output); - - private: - VizAccessor(); // Singleton - ~VizAccessor(); - - void add(Viz3d window); - void remove(const String &window_name); - - static VizAccessor * instance_; - - struct VizAccessorImpl; - VizAccessorImpl * impl_; - - friend class Viz3d; - }; } /* namespace viz */ } /* namespace cv */ diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index 59654b5c93..fe19c61721 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -121,6 +121,8 @@ namespace cv void create(const String &window_name); void release(); + + friend class VizStorage; }; } /* namespace viz */ diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 6df03e4f61..1b685e8fb5 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -135,20 +135,35 @@ namespace cv namespace viz { typedef std::map > WidgetActorMap; + typedef std::map VizMap; + typedef std::pair VizPair; + + class VizStorage + { + public: + static void unregisterAll(); + + //! window names automatically have Viz - prefix even though not provided by the users + static String generateWindowName(const String &window_name); + + private: + VizStorage(); // Static + ~VizStorage(); + + static void add(Viz3d window); + static Viz3d get(const String &window_name); + static void remove(const String &window_name); + static bool windowExists(const String &window_name); + static void removeUnreferenced(); + + static VizMap storage; + friend class Viz3d; + }; } } #include "interactor_style.h" #include "viz3d_impl.hpp" -namespace cv -{ - namespace viz - { - typedef std::map VizMap; - typedef std::pair VizPair; - } -} - #endif diff --git a/modules/viz/src/viz.cpp b/modules/viz/src/viz.cpp index 747c8de342..703da98cdc 100644 --- a/modules/viz/src/viz.cpp +++ b/modules/viz/src/viz.cpp @@ -107,70 +107,46 @@ namespace cv { namespace viz }} /////////////////////////////////////////////////////////////////////////////////////////////// -/// Viz accessor implementation +/// VizStorage implementation -cv::viz::VizAccessor * cv::viz::VizAccessor::instance_ = 0; +cv::viz::VizMap cv::viz::VizStorage::storage; +void cv::viz::VizStorage::unregisterAll() { storage.clear(); } -struct cv::viz::VizAccessor::VizAccessorImpl +cv::viz::Viz3d cv::viz::VizStorage::get(const String &window_name) { - cv::viz::VizMap viz_map; -}; - -cv::viz::VizAccessor::VizAccessor() { impl_ = new cv::viz::VizAccessor::VizAccessorImpl;} -cv::viz::VizAccessor::~VizAccessor() { delete impl_; } - -cv::viz::VizAccessor & cv::viz::VizAccessor::getInstance() -{ - if (!instance_) - instance_ = new VizAccessor(); - - return *instance_; + String name = generateWindowName(window_name); + VizMap::iterator vm_itr = storage.find(name); + CV_Assert(vm_itr != storage.end()); + return vm_itr->second; } -void cv::viz::VizAccessor::release() -{ - if (instance_) - { - delete instance_; - instance_ = 0; - } -} - -cv::viz::Viz3d cv::viz::VizAccessor::get(const String & window_name) -{ - // Add the prefix Viz - String name; - generateWindowName(window_name, name); - - VizMap::iterator vm_itr = impl_->viz_map.find(name); - return vm_itr != impl_->viz_map.end() ? vm_itr->second : Viz3d(window_name); -} - -void cv::viz::VizAccessor::add(Viz3d window) +void cv::viz::VizStorage::add(Viz3d window) { String window_name = window.getWindowName(); - VizMap::iterator vm_itr = impl_->viz_map.find(window_name); - if (vm_itr == impl_->viz_map.end()) - impl_->viz_map.insert(VizPair(window_name, window)); + VizMap::iterator vm_itr = storage.find(window_name); + CV_Assert(vm_itr == storage.end()); + storage.insert(VizPair(window_name, window)); } -void cv::viz::VizAccessor::remove(const String &window_name) +bool cv::viz::VizStorage::windowExists(const String &window_name) { - // Add the prefix Viz - String name; - generateWindowName(window_name, name); - - VizMap::iterator vm_itr = impl_->viz_map.find(name); - if (vm_itr != impl_->viz_map.end()) - impl_->viz_map.erase(vm_itr); + String name = generateWindowName(window_name); + return storage.find(name) != storage.end(); } -void cv::viz::VizAccessor::generateWindowName(const String &window_name, String &output) +void cv::viz::VizStorage::removeUnreferenced() { - output = "Viz"; + for(VizMap::iterator pos = storage.begin(); pos != storage.end(); ++pos) + if(pos->second.impl_->ref_counter == 1) + storage.erase(pos); +} + +cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) +{ + String output = "Viz"; // Already is Viz if (window_name == output) - return; + return output; String prefixed = output + " - "; if (window_name.substr(0, prefixed.length()) == prefixed) @@ -179,9 +155,9 @@ void cv::viz::VizAccessor::generateWindowName(const String &window_name, String output = prefixed + window_name; // Doesn't have prefix else output = (window_name == "" ? output : prefixed + window_name); + + return output; } -cv::viz::Viz3d cv::viz::get(const String &window_name) -{ - return cv::viz::VizAccessor::getInstance().get(window_name); -} +cv::viz::Viz3d cv::viz::get(const String &window_name) { return Viz3d(window_name); } +void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index f5a0bc8895..ec57a3f44c 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -52,7 +52,8 @@ cv::viz::Viz3d::Viz3d(const String& window_name) : impl_(0) { create(window_name cv::viz::Viz3d::Viz3d(const Viz3d& other) : impl_(other.impl_) { - if (impl_) CV_XADD(&impl_->ref_counter, 1); + if (impl_) + CV_XADD(&impl_->ref_counter, 1); } cv::viz::Viz3d& cv::viz::Viz3d::operator=(const Viz3d& other) @@ -70,24 +71,28 @@ cv::viz::Viz3d::~Viz3d() { release(); } void cv::viz::Viz3d::create(const String &window_name) { - if (impl_) release(); - impl_ = new VizImpl(window_name); - impl_->ref_counter = 1; - // Register the window - cv::viz::VizAccessor::getInstance().add(*this); + if (impl_) + release(); + + if (VizStorage::windowExists(window_name)) + *this = VizStorage::get(window_name); + else + { + impl_ = new VizImpl(window_name); + impl_->ref_counter = 1; + + // Register the window + VizStorage::add(*this); + } } void cv::viz::Viz3d::release() { - // If the current referene count is equal to 2, we can delete it - // - 2 : because minimum there will be two instances, one of which is in the map - if (impl_ && CV_XADD(&impl_->ref_counter, -1) == 2) - { - // Erase the window - cv::viz::VizAccessor::getInstance().remove(getWindowName()); + if (impl_ && CV_XADD(&impl_->ref_counter, -1) == 1) delete impl_; - impl_ = 0; - } + + impl_ = 0; + VizStorage::removeUnreferenced(); } void cv::viz::Viz3d::spin() { impl_->spin(); } From fb62a66b6962d1d0d9df4f085d05d1952f402093 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 24 Nov 2013 20:06:54 +0400 Subject: [PATCH 75/97] removed unused code --- ...nteractor_style.h => interactor_style.hpp} | 0 modules/viz/src/precomp.hpp | 7 +- modules/viz/src/viz.cpp | 2 +- modules/viz/src/viz3d_impl.cpp | 90 +------------------ modules/viz/src/viz3d_impl.hpp | 4 - 5 files changed, 8 insertions(+), 95 deletions(-) rename modules/viz/src/{interactor_style.h => interactor_style.hpp} (100%) diff --git a/modules/viz/src/interactor_style.h b/modules/viz/src/interactor_style.hpp similarity index 100% rename from modules/viz/src/interactor_style.h rename to modules/viz/src/interactor_style.hpp diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 1b685e8fb5..57b421dbbc 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -70,7 +70,7 @@ #include #include #include -#include +//#include #include #include #include @@ -105,7 +105,6 @@ #include #include #include -#include #include #include #include @@ -119,6 +118,7 @@ #include #include #include +#include #if defined __GNUC__ && defined __DEPRECATED_DISABLED__ #define __DEPRECATED @@ -136,7 +136,6 @@ namespace cv { typedef std::map > WidgetActorMap; typedef std::map VizMap; - typedef std::pair VizPair; class VizStorage { @@ -162,7 +161,7 @@ namespace cv } } -#include "interactor_style.h" +#include "interactor_style.hpp" #include "viz3d_impl.hpp" diff --git a/modules/viz/src/viz.cpp b/modules/viz/src/viz.cpp index 703da98cdc..4b88d7d185 100644 --- a/modules/viz/src/viz.cpp +++ b/modules/viz/src/viz.cpp @@ -125,7 +125,7 @@ void cv::viz::VizStorage::add(Viz3d window) String window_name = window.getWindowName(); VizMap::iterator vm_itr = storage.find(window_name); CV_Assert(vm_itr == storage.end()); - storage.insert(VizPair(window_name, window)); + storage.insert(std::make_pair(window_name, window)); } bool cv::viz::VizStorage::windowExists(const String &window_name) diff --git a/modules/viz/src/viz3d_impl.cpp b/modules/viz/src/viz3d_impl.cpp index 14107c5d1e..d868c48b0f 100644 --- a/modules/viz/src/viz3d_impl.cpp +++ b/modules/viz/src/viz3d_impl.cpp @@ -95,9 +95,9 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) timer_id_ = interactor_->CreateRepeatingTimer(5000L); // Set a simple PointPicker - vtkSmartPointer pp = vtkSmartPointer::New(); - pp->SetTolerance(pp->GetTolerance() * 2); - interactor_->SetPicker(pp); + //vtkSmartPointer pp = vtkSmartPointer::New(); + //pp->SetTolerance(pp->GetTolerance() * 2); + //interactor_->SetPicker(pp); exit_main_loop_timer_callback_ = vtkSmartPointer::New(); exit_main_loop_timer_callback_->viz_ = this; @@ -112,8 +112,7 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) ////////////////////////////// - String window_name; - VizAccessor::generateWindowName(name, window_name); + String window_name = VizStorage::generateWindowName(name); window_->SetWindowName(window_name.c_str()); } @@ -314,45 +313,6 @@ bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(const vtkSmartPointer &data, vtkSmartPointer &actor, bool use_scalars) -{ - if (!actor) - actor = vtkSmartPointer::New(); - - vtkSmartPointer mapper = vtkSmartPointer::New(); -#if VTK_MAJOR_VERSION <= 5 - mapper->SetInput(data); -#else - mapper->SetInputData(data); -#endif - - if (use_scalars) - { - vtkSmartPointer scalars = data->GetPointData()->GetScalars(); - if (scalars) - { - cv::Vec3d minmax(scalars->GetRange()); - mapper->SetScalarRange(minmax.val); - mapper->SetScalarModeToUsePointData(); - - // interpolation OFF, if data is a vtkPolyData that contains only vertices, ON for anything else. - vtkPolyData* polyData = vtkPolyData::SafeDownCast(data); - bool interpolation = (polyData && polyData->GetNumberOfCells() != polyData->GetNumberOfVerts()); - - mapper->SetInterpolateScalarsBeforeMapping(interpolation); - mapper->ScalarVisibilityOn(); - } - } - mapper->ImmediateModeRenderingOff(); - - actor->SetNumberOfCloudPoints(int(std::max(1, data->GetNumberOfPoints() / 10))); - actor->GetProperty()->SetInterpolationToFlat(); - actor->GetProperty()->BackfaceCullingOn(); - - actor->SetMapper(mapper); -} - ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color) { @@ -542,48 +502,6 @@ void cv::viz::Viz3d::VizImpl::setRepresentation(int representation) } } -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::Viz3d::VizImpl::updateCells(vtkSmartPointer &cells, vtkSmartPointer &initcells, vtkIdType nr_points) -{ - // If no init cells and cells has not been initialized... - if (!cells) - cells = vtkSmartPointer::New(); - - // If we have less values then we need to recreate the array - if (cells->GetNumberOfTuples() < nr_points) - { - cells = vtkSmartPointer::New(); - - // If init cells is given, and there's enough data in it, use it - if (initcells && initcells->GetNumberOfTuples() >= nr_points) - { - cells->DeepCopy(initcells); - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - } - else - { - // If the number of tuples is still too small, we need to recreate the array - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - vtkIdType *cell = cells->GetPointer(0); - // Fill it with 1s - std::fill(cell, cell + nr_points * 2, 1); - cell++; - for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) - *cell = i; - // Save the results in initcells - initcells = vtkSmartPointer::New(); - initcells->DeepCopy(cells); - } - } - else - { - // The assumption here is that the current set of cells has more data than needed - cells->SetNumberOfComponents(2); - cells->SetNumberOfTuples(nr_points); - } -} ////////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode) diff --git a/modules/viz/src/viz3d_impl.hpp b/modules/viz/src/viz3d_impl.hpp index 88f8424bf4..59f45a8fa0 100644 --- a/modules/viz/src/viz3d_impl.hpp +++ b/modules/viz/src/viz3d_impl.hpp @@ -52,7 +52,6 @@ struct cv::viz::Viz3d::VizImpl { public: - typedef cv::Ptr Ptr; typedef Viz3d::KeyboardCallback KeyboardCallback; typedef Viz3d::MouseCallback MouseCallback; @@ -181,9 +180,6 @@ private: bool camera_set_; bool removeActorFromRenderer(const vtkSmartPointer &actor); - - void createActorFromVTKDataSet(const vtkSmartPointer &data, vtkSmartPointer &actor, bool use_scalars = true); - void updateCells(vtkSmartPointer &cells, vtkSmartPointer &initcells, vtkIdType nr_points); }; From a6ab9be5a6a9b28fe0fc715175adf0a3604d9982 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 24 Nov 2013 20:10:14 +0400 Subject: [PATCH 76/97] removed VizAccessor from docs --- modules/viz/doc/viz3d.rst | 62 --------------------------------------- 1 file changed, 62 deletions(-) diff --git a/modules/viz/doc/viz3d.rst b/modules/viz/doc/viz3d.rst index 79e262bb91..2f8dfcd9d0 100644 --- a/modules/viz/doc/viz3d.rst +++ b/modules/viz/doc/viz3d.rst @@ -76,68 +76,6 @@ Checks **point** for nan :param p: return true if **any** of the elements of the point is *nan*. -viz::VizAccessor ----------------- -.. ocv:class:: VizAccessor - -A singleton class that provides access by name infrastructure for 3D visualization windows. :: - - class CV_EXPORTS VizAccessor - { - public: - static VizAccessor & getInstance(); - static void release(); - - Viz3d get(const String &window_name); - - //! window names automatically have Viz - prefix even though not provided by the users - static void generateWindowName(const String &window_name, String &output); - - private: - /* hidden */ - }; - -viz::VizAccessor::getInstance ------------------------------ -Returns the single instance of VizAccessor. - -.. ocv:function:: static VizAccessor & getInstance() - -viz::VizAccessor::release -------------------------- -Deletes the single instance of VizAccessor. - -.. ocv:function:: static void release() - -viz::VizAccessor::get ---------------------- -Retrieves a window by its name. - -.. ocv:function:: Viz3d get(const String &window_name) - - :param window_name: Name of the window that is to be retrieved. - -This function returns a :ocv:class:`Viz3d` object with the given name. - -.. note:: If the window with that name already exists, that window is returned. Otherwise, new window is created with the given name, and it is returned. - -.. note:: Window names are automatically prefixed by "Viz - " if it is not done by the user. - - .. code-block:: cpp - - /// window and window_2 are the same windows. - viz::Viz3d window = viz::get("myWindow"); - viz::Viz3d window_2 = viz::get("Viz - myWindow"); - -viz::VizAccessor::generateWindowName ------------------------------------- -Generates a window name by prefixing "Viz - " if it has not already been prefixed. - -.. ocv:function:: static void generateWindowName(const String &window_name, String &output) - - :param window_name: Window name - :param output: Prefixed window name - viz::Viz3d ---------- .. ocv:class:: Viz3d From 3830a0b5b239fb432dcea4c46092b2cbdbd7856a Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 24 Nov 2013 20:59:54 +0400 Subject: [PATCH 77/97] fixed bug with deletion from std::map --- modules/viz/src/precomp.hpp | 4 ++-- modules/viz/src/viz.cpp | 12 +++++++----- modules/viz/src/viz3d.cpp | 10 ++++++++-- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index 57b421dbbc..ac8c67c1bd 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -149,8 +149,8 @@ namespace cv VizStorage(); // Static ~VizStorage(); - static void add(Viz3d window); - static Viz3d get(const String &window_name); + static void add(const Viz3d& window); + static Viz3d& get(const String &window_name); static void remove(const String &window_name); static bool windowExists(const String &window_name); static void removeUnreferenced(); diff --git a/modules/viz/src/viz.cpp b/modules/viz/src/viz.cpp index 4b88d7d185..6a08dfa34a 100644 --- a/modules/viz/src/viz.cpp +++ b/modules/viz/src/viz.cpp @@ -112,7 +112,7 @@ namespace cv { namespace viz cv::viz::VizMap cv::viz::VizStorage::storage; void cv::viz::VizStorage::unregisterAll() { storage.clear(); } -cv::viz::Viz3d cv::viz::VizStorage::get(const String &window_name) +cv::viz::Viz3d& cv::viz::VizStorage::get(const String &window_name) { String name = generateWindowName(window_name); VizMap::iterator vm_itr = storage.find(name); @@ -120,7 +120,7 @@ cv::viz::Viz3d cv::viz::VizStorage::get(const String &window_name) return vm_itr->second; } -void cv::viz::VizStorage::add(Viz3d window) +void cv::viz::VizStorage::add(const Viz3d& window) { String window_name = window.getWindowName(); VizMap::iterator vm_itr = storage.find(window_name); @@ -136,9 +136,11 @@ bool cv::viz::VizStorage::windowExists(const String &window_name) void cv::viz::VizStorage::removeUnreferenced() { - for(VizMap::iterator pos = storage.begin(); pos != storage.end(); ++pos) + for(VizMap::iterator pos = storage.begin(); pos != storage.end();) if(pos->second.impl_->ref_counter == 1) - storage.erase(pos); + storage.erase(pos++); + else + ++pos; } cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) @@ -159,5 +161,5 @@ cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) return output; } -cv::viz::Viz3d cv::viz::get(const String &window_name) { return Viz3d(window_name); } +cv::viz::Viz3d cv::viz::get(const String &window_name) { return Viz3d (window_name); } void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index ec57a3f44c..08cb880dec 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -62,7 +62,8 @@ cv::viz::Viz3d& cv::viz::Viz3d::operator=(const Viz3d& other) { release(); impl_ = other.impl_; - if (impl_) CV_XADD(&impl_->ref_counter, 1); + if (impl_) + CV_XADD(&impl_->ref_counter, 1); } return *this; } @@ -89,10 +90,15 @@ void cv::viz::Viz3d::create(const String &window_name) void cv::viz::Viz3d::release() { if (impl_ && CV_XADD(&impl_->ref_counter, -1) == 1) + { delete impl_; + impl_ = 0; + } + + if (impl_ && impl_->ref_counter == 1) + VizStorage::removeUnreferenced(); impl_ = 0; - VizStorage::removeUnreferenced(); } void cv::viz::Viz3d::spin() { impl_->spin(); } From 0e88733b1385930c73b75d48388ea75cd1bce593 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sun, 24 Nov 2013 23:26:03 +0400 Subject: [PATCH 78/97] updating Viz cmake (switched to WITH_VTK option) --- CMakeLists.txt | 4 ++ cmake/OpenCVDetectVTK.cmake | 27 +++++++++++ modules/viz/CMakeLists.txt | 58 +++-------------------- modules/viz/include/opencv2/viz/viz3d.hpp | 2 +- 4 files changed, 38 insertions(+), 53 deletions(-) create mode 100644 cmake/OpenCVDetectVTK.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e27852de9..856a4d4f8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,6 +116,7 @@ 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_VTK "Include VTK library support (and build opencv_viz module eiher)" OFF IF (NOT ANDROID AND NOT IOS) ) OCV_OPTION(WITH_CUDA "Include NVidia Cuda Runtime support" ON IF (NOT IOS) ) OCV_OPTION(WITH_CUFFT "Include NVidia Cuda Fast Fourier Transform (FFT) library support" ON IF (NOT IOS) ) OCV_OPTION(WITH_CUBLAS "Include NVidia Cuda Basic Linear Algebra Subprograms (BLAS) library support" OFF IF (NOT IOS) ) @@ -430,6 +431,8 @@ endif() # --- Matlab/Octave --- include(cmake/OpenCVFindMatlab.cmake) +include(cmake/OpenCVDetectVTK.cmake) + # ---------------------------------------------------------------------------- # Add CUDA libraries (needed for apps/tools, samples) # ---------------------------------------------------------------------------- @@ -659,6 +662,7 @@ else() endif() status(" OpenGL support:" HAVE_OPENGL THEN "YES (${OPENGL_LIBRARIES})" ELSE NO) +status(" VTK support:" HAVE_VTK THEN "YES (ver ${VTK_VERSION})" ELSE NO) # ========================== MEDIA IO ========================== status("") diff --git a/cmake/OpenCVDetectVTK.cmake b/cmake/OpenCVDetectVTK.cmake new file mode 100644 index 0000000000..2b9d46ab03 --- /dev/null +++ b/cmake/OpenCVDetectVTK.cmake @@ -0,0 +1,27 @@ +if(NOT WITH_VTK OR ANDROID OR IOS) + message(STATUS "VTK support is disabled.") + return() +endif() + +find_package(VTK 6.0 QUIET COMPONENTS vtkRenderingCore vtkInteractionWidgets vtkInteractionStyle vtkIOLegacy vtkIOPLY vtkRenderingFreeType vtkRenderingLOD vtkFiltersTexture NO_MODULE) + +if(NOT DEFINED VTK_FOUND OR NOT VTK_FOUND) + find_package(VTK 5.10 QUIET COMPONENTS vtkCommon vtkFiltering vtkRendering vtkWidgets vtkImaging NO_MODULE) +endif() + +if(NOT DEFINED VTK_FOUND OR NOT VTK_FOUND) + find_package(VTK 5.8 QUIET COMPONENTS vtkCommon vtkFiltering vtkRendering vtkWidgets vtkImaging NO_MODULE) +endif() + +if(VTK_FOUND) + if (BUILD_SHARED_LIBS OR (NOT BUILD_SHARED_LIBS AND NOT VTK_BUILD_SHARED_LIBS)) + set(HAVE_VTK ON) + message(STATUS "Found VTK ver. ${VTK_VERSION} (usefile: ${VTK_USE_FILE})") + else () + set(HAVE_VTK OFF) + message(WARNING "VTK disabled. You are to build OpenCV in STATIC but VTK is SHARED!") + endif () +else() + set(HAVE_VTK OFF) + message(STATUS "VTK is not found. Please set -DVTK_DIR in CMake to VTK build directory, or set $VTK_DIR enviroment variable to VTK install subdirectory with UseVTK.cmake file (for windows)") +endif() \ No newline at end of file diff --git a/modules/viz/CMakeLists.txt b/modules/viz/CMakeLists.txt index ee6354dc97..93df8be96b 100644 --- a/modules/viz/CMakeLists.txt +++ b/modules/viz/CMakeLists.txt @@ -1,57 +1,11 @@ -macro(find_qvtk) - find_library (QVTK_LIBRARY QVTK HINTS ${VTK_DIR} ${VTK_DIR}/bin) - find_path (QVTK_INCLUDE_DIR QVTKWidget.h HINT ${VTK_INCLUDE_DIRS}) - find_package_handle_standard_args(QVTK DEFAULT_MSG QVTK_LIBRARY QVTK_INCLUDE_DIR) - - if(QVTK_FOUND) - get_filename_component (QVTK_LIBRARY_DIR ${QVTK_LIBRARY} PATH) - list(APPEND VTK_LIBRARY_DIRS ${QVTK_LIBRARY_DIR}) - list(APPEND VTK_INCLUDE_DIRS ${QVTK_INCLUDE_DIR}) - set (VTK_USE_QVTK ON) - endif() -endmacro() - -macro(find_vtk) - find_package(VTK) - if(${VTK_MAJOR_VERSION} LESS 5) - MESSAGE(FATAL_ERROR "VTK 5 or more required!") - endif() - if(VTK_FOUND) - if (BUILD_SHARED_LIBS OR (NOT BUILD_SHARED_LIBS AND NOT VTK_BUILD_SHARED_LIBS)) - find_qvtk() - message(STATUS "VTK found (include: ${VTK_INCLUDE_DIRS}, lib: ${VTK_LIBRARY_DIRS})") - link_directories(${VTK_LIBRARY_DIRS}) - include_directories(SYSTEM ${VTK_INCLUDE_DIRS}) - set(HAVE_VTK ON) - else () - set(HAVE_VTK OFF) - message (FATAL_ERROR "VTK disabled. You are to build OpenCV in STATIC but VTK is SHARED!") - endif () - endif() -endmacro() - -if (NOT OPENCV_INITIAL_PASS AND DEFINED BUILD_opencv_viz AND BUILD_opencv_viz) - find_vtk() -endif() - -if(DEFINED HAVE_VTK AND HAVE_VTK) - set(VTK_USE_FILE ${VTK_USE_FILE} CACHE INTERNAL "VTK_USE_FILE") - include (${VTK_USE_FILE}) - add_definitions(-DHAVE_VTK) +if(NOT WITH_VTK OR NOT DEFINED HAVE_VTK OR NOT HAVE_VTK) + return() endif() +include(${VTK_USE_FILE}) set(the_description "Viz") -set(BUILD_opencv_viz_INIT OFF) -include_directories(src) -ocv_define_module(viz opencv_core) +ocv_define_module(viz opencv_core ${VTK_LIBRARIES}) -if(DEFINED BUILD_opencv_viz AND BUILD_opencv_viz AND DEFINED HAVE_VTK AND HAVE_VTK) - if (${VTK_VERSION_MAJOR} EQUAL 5) - target_link_libraries(opencv_viz vtkCommon vtkWidgets vtkFiltering vtkRendering) - else() - target_link_libraries(opencv_viz vtkViewsCore vtkRenderingLOD vtkIOPLY vtkRenderingFreeTypeOpenGL vtkRenderingVolumeOpenGL vtkFiltersTexture) - endif() - if(APPLE) - target_link_libraries(opencv_viz "-framework Cocoa") - endif() +if(APPLE AND BUILD_opencv_viz) + target_link_libraries(opencv_viz "-framework Cocoa") endif() diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index fe19c61721..f19709eb52 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -49,7 +49,7 @@ #ifndef __OPENCV_VIZ_VIZ3D_HPP__ #define __OPENCV_VIZ_VIZ3D_HPP__ -#if !defined YES_I_AGREE_THAT_VIZ_API_IS_NOT_STABLE_NOW_AND_BINARY_COMPARTIBILITY_WONT_BE_SUPPORTED +#if !defined YES_I_AGREE_THAT_VIZ_API_IS_NOT_STABLE_NOW_AND_BINARY_COMPARTIBILITY_WONT_BE_SUPPORTED && !defined CVAPI_EXPORTS //#error "Viz is in beta state now. Please define macro above to use it" #endif From 546c084fe60b1c3c0abd13810ba0116733ee9ec9 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 26 Nov 2013 13:29:50 +0400 Subject: [PATCH 79/97] fixed shadow error and added ocv_disable_module --- modules/core/include/opencv2/core/affine.hpp | 14 +++++++------- modules/viz/CMakeLists.txt | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index fa7eed8638..fefcef8f12 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -161,9 +161,9 @@ cv::Affine3::Affine3(const Mat3& R, const Vec3& t) } template inline -cv::Affine3::Affine3(const Vec3& rvec, const Vec3& t) +cv::Affine3::Affine3(const Vec3& _rvec, const Vec3& t) { - rotation(rvec); + rotation(_rvec); translation(t); matrix.val[12] = matrix.val[13] = matrix.val[14] = 0; matrix.val[15] = 1; @@ -208,9 +208,9 @@ void cv::Affine3::rotation(const Mat3& R) } template inline -void cv::Affine3::rotation(const Vec3& rvec) +void cv::Affine3::rotation(const Vec3& _rvec) { - double rx = rvec[0], ry = rvec[1], rz = rvec[2]; + double rx = _rvec[0], ry = _rvec[1], rz = _rvec[2]; double theta = std::sqrt(rx*rx + ry*ry + rz*rz); if (theta < DBL_EPSILON) @@ -253,9 +253,9 @@ void cv::Affine3::rotation(const cv::Mat& data) } else if ((data.cols == 3 && data.rows == 1) || (data.cols == 1 && data.rows == 3)) { - Vec3 rvec; - data.reshape(1, 3).copyTo(rvec); - rotation(rvec); + Vec3 _rvec; + data.reshape(1, 3).copyTo(_rvec); + rotation(_rvec); } else CV_Assert(!"Input marix can be 3x3, 1x3 or 3x1"); diff --git a/modules/viz/CMakeLists.txt b/modules/viz/CMakeLists.txt index 93df8be96b..6da1afc11a 100644 --- a/modules/viz/CMakeLists.txt +++ b/modules/viz/CMakeLists.txt @@ -1,5 +1,5 @@ if(NOT WITH_VTK OR NOT DEFINED HAVE_VTK OR NOT HAVE_VTK) - return() + ocv_module_disable() endif() include(${VTK_USE_FILE}) From a54ef70c045493e24f862bbaccbcf1101142ac09 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Tue, 26 Nov 2013 15:40:57 +0400 Subject: [PATCH 80/97] minor insignificant corrections --- cmake/OpenCVDetectVTK.cmake | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/cmake/OpenCVDetectVTK.cmake b/cmake/OpenCVDetectVTK.cmake index 2b9d46ab03..f0d28d552a 100644 --- a/cmake/OpenCVDetectVTK.cmake +++ b/cmake/OpenCVDetectVTK.cmake @@ -1,5 +1,4 @@ if(NOT WITH_VTK OR ANDROID OR IOS) - message(STATUS "VTK support is disabled.") return() endif() @@ -14,14 +13,9 @@ if(NOT DEFINED VTK_FOUND OR NOT VTK_FOUND) endif() if(VTK_FOUND) - if (BUILD_SHARED_LIBS OR (NOT BUILD_SHARED_LIBS AND NOT VTK_BUILD_SHARED_LIBS)) - set(HAVE_VTK ON) - message(STATUS "Found VTK ver. ${VTK_VERSION} (usefile: ${VTK_USE_FILE})") - else () - set(HAVE_VTK OFF) - message(WARNING "VTK disabled. You are to build OpenCV in STATIC but VTK is SHARED!") - endif () + set(HAVE_VTK ON) + message(STATUS "Found VTK ver. ${VTK_VERSION} (usefile: ${VTK_USE_FILE})") else() set(HAVE_VTK OFF) - message(STATUS "VTK is not found. Please set -DVTK_DIR in CMake to VTK build directory, or set $VTK_DIR enviroment variable to VTK install subdirectory with UseVTK.cmake file (for windows)") + message(STATUS "VTK is not found. Please set -DVTK_DIR in CMake to VTK build directory, or set $VTK_DIR enviroment variable to VTK install subdirectory with VTKConfig.cmake file (for windows)") endif() \ No newline at end of file From f9ca6cfd22611b0024c2c75fd2891e6b54a5b101 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Thu, 28 Nov 2013 12:10:28 +0400 Subject: [PATCH 81/97] fixed ocv_module_disable() --- modules/viz/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/viz/CMakeLists.txt b/modules/viz/CMakeLists.txt index 6da1afc11a..7ccd079216 100644 --- a/modules/viz/CMakeLists.txt +++ b/modules/viz/CMakeLists.txt @@ -1,5 +1,5 @@ if(NOT WITH_VTK OR NOT DEFINED HAVE_VTK OR NOT HAVE_VTK) - ocv_module_disable() + ocv_module_disable(viz) endif() include(${VTK_USE_FILE}) From f62ffa2aea67ba1fbfe6806a8e54e04dbf0294ed Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 30 Nov 2013 18:02:57 +0400 Subject: [PATCH 82/97] compilation --- modules/highgui/src/cap_openni.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/highgui/src/cap_openni.cpp b/modules/highgui/src/cap_openni.cpp index c509c1e657..cc68a23bfa 100644 --- a/modules/highgui/src/cap_openni.cpp +++ b/modules/highgui/src/cap_openni.cpp @@ -152,7 +152,7 @@ public: task = new( tbb::task::allocate_root() ) TBBApproximateSynchronizerTask( *this ); tbb::task::enqueue(*task); #else - task->reset( new ApproximateSynchronizer( *this ) ); + task.reset( new ApproximateSynchronizer( *this ) ); #endif } From 4c66b87698f77549614e0c9473c673c380f530a2 Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Sat, 7 Dec 2013 19:07:24 +0400 Subject: [PATCH 83/97] fixed -Wshadow and other warnings, added rvec test --- modules/calib3d/test/test_affine3.cpp | 27 +++++++++++++++++++++++ modules/viz/include/opencv2/viz/types.hpp | 4 ++-- modules/viz/src/precomp.hpp | 14 ------------ modules/viz/src/viz3d_impl.cpp | 6 +++-- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/modules/calib3d/test/test_affine3.cpp b/modules/calib3d/test/test_affine3.cpp index 62326e9203..cc94d99c19 100644 --- a/modules/calib3d/test/test_affine3.cpp +++ b/modules/calib3d/test/test_affine3.cpp @@ -79,3 +79,30 @@ TEST(Calib3d_Affine3f, accuracy) ASSERT_LT(cv::norm(diff, cv::NORM_INF), 1e-15); } + +TEST(Calib3d_Affine3f, accuracy_rvec) +{ + cv::RNG rng; + typedef float T; + + cv::Affine3::Vec3 w; + cv::Affine3::Mat3 u, vt, R; + + for(int i = 0; i < 100; ++i) + { + rng.fill(R, cv::RNG::UNIFORM, -10, 10, true); + cv::SVD::compute(R, w, u, vt, cv::SVD::FULL_UV + cv::SVD::MODIFY_A); + R = u * vt; + + //double s = (double)cv::getTickCount(); + cv::Affine3::Vec3 va = cv::Affine3(R).rvec(); + //std::cout << "M:" <<(cv::getTickCount() - s)*1000/cv::getTickFrequency() << std::endl; + + cv::Affine3::Vec3 vo; + //s = (double)cv::getTickCount(); + cv::Rodrigues(R, vo); + //std::cout << "O:" <<(cv::getTickCount() - s)*1000/cv::getTickFrequency() << std::endl; + + ASSERT_LT(cv::norm(va - vo), 1e-9); + } +} diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index 3cccfa06fe..682006f959 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -176,8 +176,8 @@ namespace cv /// cv::viz::Color inline cv::viz::Color::Color() : Scalar(0, 0, 0) {} -inline cv::viz::Color::Color(double gray) : Scalar(gray, gray, gray) {} -inline cv::viz::Color::Color(double blue, double green, double red) : Scalar(blue, green, red) {} +inline cv::viz::Color::Color(double _gray) : Scalar(_gray, _gray, _gray) {} +inline cv::viz::Color::Color(double _blue, double _green, double _red) : Scalar(_blue, _green, _red) {} inline cv::viz::Color::Color(const Scalar& color) : Scalar(color) {} inline cv::viz::Color cv::viz::Color::black() { return Color( 0, 0, 0); } diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index ac8c67c1bd..ab673b389c 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -54,14 +54,6 @@ #include #include -#if defined __GNUC__ -#pragma GCC system_header -#ifdef __DEPRECATED -#undef __DEPRECATED -#define __DEPRECATED_DISABLED__ -#endif -#endif - #include #include #include @@ -70,7 +62,6 @@ #include #include #include -//#include #include #include #include @@ -120,11 +111,6 @@ #include #include -#if defined __GNUC__ && defined __DEPRECATED_DISABLED__ -#define __DEPRECATED -#undef __DEPRECATED_DISABLED__ -#endif - #include #include #include diff --git a/modules/viz/src/viz3d_impl.cpp b/modules/viz/src/viz3d_impl.cpp index d868c48b0f..b1173f645d 100644 --- a/modules/viz/src/viz3d_impl.cpp +++ b/modules/viz/src/viz3d_impl.cpp @@ -48,6 +48,8 @@ #include "precomp.hpp" +vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew(); + #if 1 || !defined __APPLE__ vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew() { @@ -57,7 +59,7 @@ vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew() ///////////////////////////////////////////////////////////////////////////////////////////// cv::viz::Viz3d::VizImpl::VizImpl(const String &name) - : style_(vtkSmartPointer::New()) , widget_actor_map_(new WidgetActorMap), s_lastDone_(0.0) + : s_lastDone_(0.0), style_(vtkSmartPointer::New()), widget_actor_map_(new WidgetActorMap) { renderer_ = vtkSmartPointer::New(); @@ -77,7 +79,7 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) style_->UseTimersOn(); ///////////////////////////////////////////////// - interactor_ = vtkSmartPointer ::Take(vtkRenderWindowInteractorFixNew()); + interactor_ = vtkSmartPointer::Take(vtkRenderWindowInteractorFixNew()); window_->AlphaBitPlanesOff(); window_->PointSmoothingOff(); From cd3f7fbf053ad3d4d18b925c7d90f0d5e0db3749 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sun, 8 Dec 2013 01:32:17 +0400 Subject: [PATCH 84/97] added cv::merge to T-API --- modules/core/src/convert.cpp | 54 ++++++ modules/core/src/matrix.cpp | 14 ++ modules/core/src/ocl.cpp | 23 ++- modules/core/src/opencl/split_merge.cl | 83 +++++++++ modules/core/test/ocl/test_arithm.cpp | 4 - modules/core/test/ocl/test_split_merge.cpp | 201 +++++++++++++++++++++ 6 files changed, 367 insertions(+), 12 deletions(-) create mode 100644 modules/core/src/opencl/split_merge.cl create mode 100644 modules/core/test/ocl/test_split_merge.cpp diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index af7e042e18..c6cc0fd747 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -353,8 +353,62 @@ void cv::merge(const Mat* mv, size_t n, OutputArray _dst) } } +namespace cv { + +static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst ) +{ + const std::vector & src = *(const std::vector *)(_mv.getObj()); + CV_Assert(!src.empty()); + + int type = src[0].type(), depth = CV_MAT_DEPTH(type); + Size size = src[0].size(); + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; + + if (doubleSupport && depth == CV_64F) + return false; + + size_t srcsize = src.size(); + for (size_t i = 0; i < srcsize; ++i) + { + int itype = src[i].type(), icn = CV_MAT_CN(itype), idepth = CV_MAT_DEPTH(itype); + if (src[i].dims > 2 || icn != 1) + return false; + CV_Assert(size == src[i].size() && depth == idepth); + } + + String srcargs, srcdecl, processelem; + for (size_t i = 0; i < srcsize; ++i) + { + srcargs += format("DECLARE_SRC_PARAM(%d)", i); + srcdecl += format("DECLARE_DATA(%d)", i); + processelem += format("PROCESS_ELEM(%d)", i); + } + + ocl::Kernel k("merge", ocl::core::split_merge_oclsrc, + format("-D OP_MERGE -D cn=%d -D T=%s -D DECLARE_SRC_PARAMS_N=%s -D DECLARE_DATA_N=%s -D PROCESS_ELEMS_N=%s", + (int)srcsize, ocl::memopTypeToStr(depth), srcargs.c_str(), srcdecl.c_str(), processelem.c_str())); + if (k.empty()) + return false; + + _dst.create(size, CV_MAKE_TYPE(depth, srcsize)); + UMat dst = _dst.getUMat(); + + int argidx = 0; + for (size_t i = 0; i < srcsize; ++i) + argidx = k.set(argidx, ocl::KernelArg::ReadOnlyNoSize(src[i])); + k.set(argidx, ocl::KernelArg::WriteOnly(dst)); + + size_t globalsize[2] = { dst.cols, dst.rows }; + return k.run(2, globalsize, NULL, false); +} + +} + void cv::merge(InputArrayOfArrays _mv, OutputArray _dst) { + if (ocl::useOpenCL() && _mv.isUMatVector() && _dst.isUMat() && ocl_merge(_mv, _dst)) + return; + std::vector mv; _mv.getMatVector(mv); merge(!mv.empty() ? &mv[0] : 0, mv.size(), _dst); diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 72c6c4756d..871fb385d6 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -1822,6 +1822,13 @@ size_t _InputArray::offset(int i) const return (size_t)(vv[i].data - vv[i].datastart); } + if( k == STD_VECTOR_UMAT ) + { + const std::vector& vv = *(const std::vector*)obj; + CV_Assert((size_t)i < vv.size()); + return vv[i].offset; + } + if( k == GPU_MAT ) { CV_Assert( i < 0 ); @@ -1861,6 +1868,13 @@ size_t _InputArray::step(int i) const return vv[i].step; } + if( k == STD_VECTOR_UMAT ) + { + const std::vector& vv = *(const std::vector*)obj; + CV_Assert((size_t)i < vv.size()); + return vv[i].step; + } + if( k == GPU_MAT ) { CV_Assert( i < 0 ); diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index f733dd11fb..5fb0d35760 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -1893,7 +1893,7 @@ Context2& Context2::getDefault() // First, try to retrieve existing context of the same type. // In its turn, Platform::getContext() may call Context2::create() // if there is no such context. - ctx.create(Device::TYPE_ACCELERATOR); + ctx.create(Device::TYPE_CPU); if(!ctx.p) ctx.create(Device::TYPE_DGPU); if(!ctx.p) @@ -2189,8 +2189,13 @@ int Kernel::set(int i, const void* value, size_t sz) CV_Assert(i >= 0); if( i == 0 ) p->cleanupUMats(); - if( !p || !p->handle || clSetKernelArg(p->handle, (cl_uint)i, sz, value) < 0 ) + cl_int retval; + if( !p || !p->handle || (retval = clSetKernelArg(p->handle, (cl_uint)i, sz, value)) < 0 ) + { + printf("%d\n", retval); return -1; + } + printf("%d\n", retval); return i+1; } @@ -2201,6 +2206,7 @@ int Kernel::set(int i, const UMat& m) int Kernel::set(int i, const KernelArg& arg) { + printf("Setting to index %d\n", i); CV_Assert( i >= 0 ); if( !p || !p->handle ) return -1; @@ -2214,20 +2220,21 @@ int Kernel::set(int i, const KernelArg& arg) cl_mem h = (cl_mem)arg.m->handle(accessFlags); if (ptronly) - clSetKernelArg(p->handle, (cl_uint)i++, sizeof(h), &h); + printf("%d\n", clSetKernelArg(p->handle, (cl_uint)i++, sizeof(h), &h)); else if( arg.m->dims <= 2 ) { UMat2D u2d(*arg.m); - clSetKernelArg(p->handle, (cl_uint)i, sizeof(h), &h); - clSetKernelArg(p->handle, (cl_uint)(i+1), sizeof(u2d.step), &u2d.step); - clSetKernelArg(p->handle, (cl_uint)(i+2), sizeof(u2d.offset), &u2d.offset); + printf("setting ... \n"); + printf("%d\n", clSetKernelArg(p->handle, (cl_uint)i, sizeof(h), &h)); + printf("%d\n", clSetKernelArg(p->handle, (cl_uint)(i+1), sizeof(u2d.step), &u2d.step)); + printf("%d\n", clSetKernelArg(p->handle, (cl_uint)(i+2), sizeof(u2d.offset), &u2d.offset)); i += 3; if( !(arg.flags & KernelArg::NO_SIZE) ) { int cols = u2d.cols*arg.wscale; - clSetKernelArg(p->handle, (cl_uint)i, sizeof(u2d.rows), &u2d.rows); - clSetKernelArg(p->handle, (cl_uint)(i+1), sizeof(cols), &cols); + printf("%d\n", clSetKernelArg(p->handle, (cl_uint)i, sizeof(u2d.rows), &u2d.rows)); + printf("%d\n", clSetKernelArg(p->handle, (cl_uint)(i+1), sizeof(cols), &cols)); i += 2; } } diff --git a/modules/core/src/opencl/split_merge.cl b/modules/core/src/opencl/split_merge.cl new file mode 100644 index 0000000000..2fd7b515cc --- /dev/null +++ b/modules/core/src/opencl/split_merge.cl @@ -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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, 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 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*/ + +#ifdef OP_MERGE + +#define DECLARE_SRC_PARAM(index) __global const uchar * src##index##ptr, int src##index##_step, int src##index##_offset, +#define DECLARE_DATA(index) __global const T * src##index = \ + (__global T *)(src##index##ptr + mad24(src##index##_step, y, x * (int)sizeof(T) + src##index##_offset)); +#define PROCESS_ELEM(index) dst[index] = src##index[0]; + +__kernel void merge(DECLARE_SRC_PARAMS_N + __global uchar * dstptr, int dst_step, int dst_offset, + int rows, int cols) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if (x < cols && y < rows) + { + DECLARE_DATA_N + __global T * dst = (__global T *)(dstptr + mad24(dst_step, y, x * (int)sizeof(T) * cn + dst_offset)); + PROCESS_ELEMS_N + } +} + +#elif defined OP_SPLIT + +__kernel void set(__global uchar* dstptr, int dststep, int dstoffset, + int rows, int cols, dstT value ) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if (x < cols && y < rows) + { + int dst_index = mad24(y, dststep, x*(int)sizeof(dstT) + dstoffset); + *(__global dstT*)(dstptr + dst_index) = value; + } +} + +#else +#error "No operation" +#endif diff --git a/modules/core/test/ocl/test_arithm.cpp b/modules/core/test/ocl/test_arithm.cpp index 844be7bdf2..9ef0d21313 100644 --- a/modules/core/test/ocl/test_arithm.cpp +++ b/modules/core/test/ocl/test_arithm.cpp @@ -42,8 +42,6 @@ #include "test_precomp.hpp" #include "opencv2/ts/ocl_test.hpp" -#ifdef HAVE_OPENCL - namespace cvtest { namespace ocl { @@ -1036,5 +1034,3 @@ OCL_INSTANTIATE_TEST_CASE_P(Arithm, Magnitude, Combine(::testing::Values(CV_32F, OCL_INSTANTIATE_TEST_CASE_P(Arithm, Flip, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); } } // namespace cvtest::ocl - -#endif // HAVE_OPENCL diff --git a/modules/core/test/ocl/test_split_merge.cpp b/modules/core/test/ocl/test_split_merge.cpp new file mode 100644 index 0000000000..70ba2d5020 --- /dev/null +++ b/modules/core/test/ocl/test_split_merge.cpp @@ -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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Jia Haipeng, jiahaipeng95@gmail.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 materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including 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/ts/ocl_test.hpp" + +namespace cvtest { +namespace ocl { + +PARAM_TEST_CASE(MergeTestBase, MatDepth, Channels, bool) +{ + int depth, cn; + bool use_roi; + + TEST_DECLARE_INPUT_PARAMETER(src1) + TEST_DECLARE_INPUT_PARAMETER(src2) + TEST_DECLARE_INPUT_PARAMETER(src3) + TEST_DECLARE_INPUT_PARAMETER(src4) + TEST_DECLARE_OUTPUT_PARAMETER(dst) + + std::vector src_roi; + std::vector usrc_roi; + + virtual void SetUp() + { + depth = GET_PARAM(0); + cn = GET_PARAM(1); + use_roi = GET_PARAM(2); + } + + virtual void random_roi() + { + CV_Assert(cn >= 1 && cn <= 4); + Size roiSize = randomSize(1, MAX_VALUE); + + { + Border src1Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src1, src1_roi, roiSize, src1Border, depth, 2, 11); + + Border src2Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src2, src2_roi, roiSize, src2Border, depth, -1540, 1740); + + Border src3Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src3, src3_roi, roiSize, src3Border, depth, -1540, 1740); + + Border src4Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src4, src4_roi, roiSize, src4Border, depth, -1540, 1740); + } + + Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst, dst_roi, roiSize, dstBorder, CV_MAKE_TYPE(depth, cn), 5, 16); + + UMAT_UPLOAD_INPUT_PARAMETER(src1) + UMAT_UPLOAD_INPUT_PARAMETER(src2) + UMAT_UPLOAD_INPUT_PARAMETER(src3) + UMAT_UPLOAD_INPUT_PARAMETER(src4) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst) + + src_roi.push_back(src1_roi), usrc_roi.push_back(usrc1_roi); + if (cn >= 2) + src_roi.push_back(src2_roi), usrc_roi.push_back(usrc2_roi); + if (cn >= 3) + src_roi.push_back(src3_roi), usrc_roi.push_back(usrc3_roi); + if (cn >= 4) + src_roi.push_back(src4_roi), usrc_roi.push_back(usrc4_roi); + } + + void Near(double threshold = 0.) + { + EXPECT_MAT_NEAR(dst, udst, threshold); + EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold); + } +}; + +typedef MergeTestBase Merge; + +OCL_TEST_P(Merge, Accuracy) +{ + for(int j = 0; j < test_loop_times; j++) + { + random_roi(); + + OCL_OFF(cv::merge(src_roi, dst_roi)); + OCL_ON(cv::merge(usrc_roi, udst_roi)); + + Near(); + } +} + +//PARAM_TEST_CASE(SplitTestBase, MatType, int, bool) +//{ +// int type; +// int channels; +// bool use_roi; + +// cv::Mat src, src_roi; +// cv::Mat dst[MAX_CHANNELS], dst_roi[MAX_CHANNELS]; + +// cv::ocl::oclMat gsrc_whole, gsrc_roi; +// cv::ocl::oclMat gdst_whole[MAX_CHANNELS], gdst_roi[MAX_CHANNELS]; + +// virtual void SetUp() +// { +// type = GET_PARAM(0); +// channels = GET_PARAM(1); +// use_roi = GET_PARAM(2); +// } + +// void random_roi() +// { +// Size roiSize = randomSize(1, MAX_VALUE); +// Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); +// randomSubMat(src, src_roi, roiSize, srcBorder, CV_MAKETYPE(type, channels), 0, 256); +// generateOclMat(gsrc_whole, gsrc_roi, src, roiSize, srcBorder); + +// for (int i = 0; i < channels; ++i) +// { +// Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); +// randomSubMat(dst[i], dst_roi[i], roiSize, dstBorder, CV_MAKETYPE(type, 1), 5, 16); +// generateOclMat(gdst_whole[i], gdst_roi[i], dst[i], roiSize, dstBorder); +// } +// } +//}; + +//struct Split : SplitTestBase {}; + +//#ifdef ANDROID +//// NOTE: The test fail on Android is the top of the iceberg only +//// The real fail reason is memory access vialation somewhere else +//OCL_TEST_P(Split, DISABLED_Accuracy) +//#else +//OCL_TEST_P(Split, Accuracy) +//#endif +//{ +// for(int j = 0; j < LOOP_TIMES; j++) +// { +// random_roi(); + +// cv::split(src_roi, dst_roi); +// cv::ocl::split(gsrc_roi, gdst_roi); + +// for (int i = 0; i < channels; ++i) +// { +// EXPECT_MAT_NEAR(dst[i], gdst_whole[i], 0.0); +// EXPECT_MAT_NEAR(dst_roi[i], gdst_roi[i], 0.0); +// } +// } +//} + + +OCL_INSTANTIATE_TEST_CASE_P(SplitMerge, Merge, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); + + +//INSTANTIATE_TEST_CASE_P(SplitMerge, Split , Combine( +// Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F), Values(1, 2, 3, 4), Bool())); + + +} } // namespace cvtest::ocl From b6c33bf86b9986911782dd92f7b43fabe20b80e6 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Fri, 6 Dec 2013 19:04:50 +0400 Subject: [PATCH 85/97] added cv::norm to T-API --- modules/core/src/ocl.cpp | 2 +- modules/core/src/opencl/arithm.cl | 21 +++-- modules/core/src/stat.cpp | 120 ++++++++++++++++++++++++-- modules/core/test/ocl/test_arithm.cpp | 119 +++++++++++++++++++++++-- 4 files changed, 242 insertions(+), 20 deletions(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index f733dd11fb..0cff7b5fdd 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -2379,7 +2379,7 @@ struct Program::Impl size_t retsz = 0; retval = clGetProgramBuildInfo(handle, (cl_device_id)deviceList[0], CL_PROGRAM_BUILD_LOG, 0, 0, &retsz); - if( retval >= 0 && retsz > 0 ) + if( retval >= 0 && retsz > 1 ) { AutoBuffer bufbuf(retsz + 16); char* buf = bufbuf; diff --git a/modules/core/src/opencl/arithm.cl b/modules/core/src/opencl/arithm.cl index b4cdb53f2c..9c86057caa 100644 --- a/modules/core/src/opencl/arithm.cl +++ b/modules/core/src/opencl/arithm.cl @@ -58,10 +58,10 @@ */ #ifdef DOUBLE_SUPPORT -#ifdef cl_khr_fp64 -#pragma OPENCL EXTENSION cl_khr_fp64:enable -#elif defined (cl_amd_fp64) +#ifdef cl_amd_fp64 #pragma OPENCL EXTENSION cl_amd_fp64:enable +#elif defined cl_khr_fp64 +#pragma OPENCL EXTENSION cl_khr_fp64:enable #endif #define CV_EPSILON DBL_EPSILON #define CV_PI M_PI @@ -76,12 +76,18 @@ #ifndef workT + #ifndef srcT1 #define srcT1 dstT + #endif + #ifndef srcT2 #define srcT2 dstT + #endif #define workT dstT - #define srcelem1 *(__global dstT*)(srcptr1 + src1_index) - #define srcelem2 *(__global dstT*)(srcptr2 + src2_index) + #define srcelem1 *(__global srcT1*)(srcptr1 + src1_index) + #define srcelem2 *(__global srcT2*)(srcptr2 + src2_index) + #ifndef convertToDT #define convertToDT noconvert + #endif #else @@ -160,6 +166,11 @@ #elif defined OP_MAG #define PROCESS_ELEM dstelem = hypot(srcelem1, srcelem2) +#elif defined OP_ABS_NOSAT +#define PROCESS_ELEM \ + dstT v = convertToDT(srcelem1); \ + dstelem = v >= 0 ? v : -v + #elif defined OP_PHASE_RADIANS #define PROCESS_ELEM \ workT tmp = atan2(srcelem2, srcelem1); \ diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index b19be3b476..d04857ce81 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -1760,15 +1760,76 @@ static NormDiffFunc getNormDiffFunc(int normType, int depth) } +namespace cv { + +static bool ocl_norm( InputArray _src, int normType, double & result ) +{ + int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; + + if ( !(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2) || + (!doubleSupport && depth == CV_64F)) + return false; + + UMat src = _src.getUMat(); + + if (normType == NORM_INF) + { + UMat abssrc; + + if (depth != CV_8U && depth != CV_16U) + { + int wdepth = std::max(CV_32S, depth); + char cvt[50]; + + ocl::Kernel kabs("KF", ocl::core::arithm_oclsrc, + format("-D UNARY_OP -D OP_ABS_NOSAT -D dstT=%s -D srcT1=%s -D convertToDT=%s%s", + ocl::typeToStr(wdepth), ocl::typeToStr(depth), + ocl::convertTypeStr(depth, wdepth, 1, cvt), + doubleSupport ? " -D DOUBLE_SUPPORT" : "")); + if (kabs.empty()) + return false; + + abssrc.create(src.size(), CV_MAKE_TYPE(wdepth, cn)); + kabs.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(abssrc, cn)); + + size_t globalsize[2] = { src.cols * cn, src.rows }; + if (!kabs.run(2, globalsize, NULL, false)) + return false; + } + else + abssrc = src; + + cv::minMaxIdx(abssrc.reshape(1), NULL, &result); + } + else if (normType == NORM_L1 || normType == NORM_L2) + { + Scalar s; + bool unstype = depth == CV_8U || depth == CV_16U; + + ocl_sum(src.reshape(1), s, normType == NORM_L2 ? + OCL_OP_SUM_SQR : (unstype ? OCL_OP_SUM : OCL_OP_SUM_ABS) ); + result = normType == NORM_L1 ? s[0] : std::sqrt(s[0]); + } + + return true; +} + +} + double cv::norm( InputArray _src, int normType, InputArray _mask ) { - Mat src = _src.getMat(), mask = _mask.getMat(); - int depth = src.depth(), cn = src.channels(); - - normType &= 7; + normType &= NORM_TYPE_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) ); + ((normType == NORM_HAMMING || normType == NORM_HAMMING2) && _src.type() == CV_8U) ); + + double _result = 0; + if (ocl::useOpenCL() && _mask.empty() && _src.isUMat() && _src.dims() <= 2 && ocl_norm(_src, normType, _result)) + return _result; + + Mat src = _src.getMat(), mask = _mask.getMat(); + int depth = src.depth(), cn = src.channels(); #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) size_t total_size = src.total(); @@ -2047,9 +2108,56 @@ double cv::norm( InputArray _src, int normType, InputArray _mask ) return result.d; } +namespace cv { + +static bool ocl_norm( InputArray _src1, InputArray _src2, int normType, double & result ) +{ + int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; + bool relative = (normType & NORM_RELATIVE) != 0; + normType &= ~NORM_RELATIVE; + + if ( !(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2) || + (!doubleSupport && depth == CV_64F)) + return false; + + int wdepth = std::max(CV_32S, depth); + char cvt[50]; + ocl::Kernel k("KF", ocl::core::arithm_oclsrc, + format("-D BINARY_OP -D OP_ABSDIFF -D dstT=%s -D workT=dstT -D srcT1=%s -D srcT2=srcT1" + " -D convertToDT=%s -D convertToWT1=convertToDT -D convertToWT2=convertToDT%s", + ocl::typeToStr(wdepth), ocl::typeToStr(depth), + ocl::convertTypeStr(depth, wdepth, 1, cvt), + doubleSupport ? " -D DOUBLE_SUPPORT" : "")); + if (k.empty()) + return false; + + UMat src1 = _src1.getUMat(), src2 = _src2.getUMat(), diff(src1.size(), CV_MAKE_TYPE(wdepth, cn)); + k.args(ocl::KernelArg::ReadOnlyNoSize(src1), ocl::KernelArg::ReadOnlyNoSize(src2), + ocl::KernelArg::WriteOnly(diff, cn)); + + size_t globalsize[2] = { diff.cols * cn, diff.rows }; + if (!k.run(2, globalsize, NULL, false)) + return false; + + result = cv::norm(diff, normType); + if (relative) + result /= cv::norm(src2, normType) + DBL_EPSILON; + + return true; +} + +} double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask ) { + CV_Assert( _src1.size() == _src2.size() && _src1.type() == _src2.type() ); + + double _result = 0; + if (ocl::useOpenCL() && _mask.empty() && _src1.isUMat() && _src2.isUMat() && + _src1.dims() <= 2 && _src2.dims() <= 2 && ocl_norm(_src1, _src2, normType, _result)) + return _result; + if( normType & CV_RELATIVE ) { #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) @@ -2135,7 +2243,7 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat(); int depth = src1.depth(), cn = src1.channels(); - CV_Assert( src1.size == src2.size && src1.type() == src2.type() ); + CV_Assert( src1.size == src2.size ); normType &= 7; CV_Assert( normType == NORM_INF || normType == NORM_L1 || diff --git a/modules/core/test/ocl/test_arithm.cpp b/modules/core/test/ocl/test_arithm.cpp index 844be7bdf2..045fbd7c49 100644 --- a/modules/core/test/ocl/test_arithm.cpp +++ b/modules/core/test/ocl/test_arithm.cpp @@ -795,8 +795,8 @@ struct RepeatTestCase : { const int type = CV_MAKE_TYPE(depth, cn); - nx = 2;//randomInt(1, 4); - ny = 2;//randomInt(1, 4); + nx = randomInt(1, 4); + ny = randomInt(1, 4); Size srcRoiSize = randomSize(1, MAX_VALUE); Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); @@ -813,7 +813,7 @@ struct RepeatTestCase : typedef RepeatTestCase Repeat; -OCL_TEST_P(Repeat, DISABLED_Mat) +OCL_TEST_P(Repeat, Mat) { for (int i = 0; i < test_loop_times; ++i) { @@ -1004,6 +1004,108 @@ OCL_TEST_P(Flip, BOTH) } } +//////////////////////////////// Norm ///////////////////////////////////////////////// + +static bool relativeError(double actual, double expected, double eps) +{ + return std::abs(actual - expected) / actual < eps; +} + +typedef ArithmTestBase Norm; + +OCL_TEST_P(Norm, NORM_INF_1arg) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(const double cpuRes = cv::norm(src1_roi, NORM_INF)); + OCL_ON(const double gpuRes = cv::norm(usrc1_roi, NORM_INF)); + + EXPECT_NEAR(cpuRes, gpuRes, 0.1); + } +} + +OCL_TEST_P(Norm, NORM_L1_1arg) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(const double cpuRes = cv::norm(src1_roi, NORM_L1)); + OCL_ON(const double gpuRes = cv::norm(usrc1_roi, NORM_L1)); + + EXPECT_PRED3(relativeError, cpuRes, gpuRes, 1e-6); + } +} + +OCL_TEST_P(Norm, NORM_L2_1arg) +{ + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + OCL_OFF(const double cpuRes = cv::norm(src1_roi, NORM_L2)); + OCL_ON(const double gpuRes = cv::norm(usrc1_roi, NORM_L2)); + + EXPECT_PRED3(relativeError, cpuRes, gpuRes, 1e-6); + } +} + +OCL_TEST_P(Norm, NORM_INF_2args) +{ + for (int relative = 0; relative < 2; ++relative) + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + int type = NORM_INF; + if (relative == 1) + type |= NORM_RELATIVE; + + OCL_OFF(const double cpuRes = cv::norm(src1_roi, src2_roi, type)); + OCL_ON(const double gpuRes = cv::norm(usrc1_roi, usrc2_roi, type)); + + EXPECT_NEAR(cpuRes, gpuRes, 0.1); + } +} + +OCL_TEST_P(Norm, NORM_L1_2args) +{ + for (int relative = 0; relative < 2; ++relative) + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + int type = NORM_L1; + if (relative == 1) + type |= NORM_RELATIVE; + + OCL_OFF(const double cpuRes = cv::norm(src1_roi, src2_roi, type)); + OCL_ON(const double gpuRes = cv::norm(usrc1_roi, usrc2_roi, type)); + + EXPECT_PRED3(relativeError, cpuRes, gpuRes, 1e-6); + } +} + +OCL_TEST_P(Norm, NORM_L2_2args) +{ + for (int relative = 0; relative < 2; ++relative) + for (int j = 0; j < test_loop_times; j++) + { + generateTestData(); + + int type = NORM_L2; + if (relative == 1) + type |= NORM_RELATIVE; + + OCL_OFF(const double cpuRes = cv::norm(src1_roi, src2_roi, type)); + OCL_ON(const double gpuRes = cv::norm(usrc1_roi, usrc2_roi, type)); + + EXPECT_PRED3(relativeError, cpuRes, gpuRes, 1e-6); + } +} + //////////////////////////////////////// Instantiation ///////////////////////////////////////// OCL_INSTANTIATE_TEST_CASE_P(Arithm, Lut, Combine(::testing::Values(CV_8U, CV_8S), OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool(), Bool())); @@ -1017,10 +1119,10 @@ OCL_INSTANTIATE_TEST_CASE_P(Arithm, Absdiff, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHA OCL_INSTANTIATE_TEST_CASE_P(Arithm, CartToPolar, Combine(testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Arithm, PolarToCart, Combine(testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Arithm, Transpose, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); -//OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_and, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); -//OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_not, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); -//OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_xor, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); -//OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_or, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_and, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_not, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_xor, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_or, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Arithm, Pow, Combine(testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Arithm, Compare, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Arithm, AddWeighted, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); @@ -1033,7 +1135,8 @@ OCL_INSTANTIATE_TEST_CASE_P(Arithm, Log, Combine(::testing::Values(CV_32F, CV_64 OCL_INSTANTIATE_TEST_CASE_P(Arithm, Exp, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Arithm, Phase, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool())); OCL_INSTANTIATE_TEST_CASE_P(Arithm, Magnitude, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool())); -OCL_INSTANTIATE_TEST_CASE_P(Arithm, Flip, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Arithm, Flip, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Arithm, Norm, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); } } // namespace cvtest::ocl From c16c9a2e8e239b2b50144046928549778038c1c3 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sun, 8 Dec 2013 14:45:25 +0400 Subject: [PATCH 86/97] added cv::split to T-API --- modules/core/src/convert.cpp | 48 +++++++- modules/core/src/ocl.cpp | 23 ++-- modules/core/src/opencl/split_merge.cl | 13 +- modules/core/test/ocl/test_arithm.cpp | 4 + modules/core/test/ocl/test_split_merge.cpp | 136 ++++++++++++--------- 5 files changed, 143 insertions(+), 81 deletions(-) diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index c6cc0fd747..1b1ceac2c4 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -264,8 +264,50 @@ void cv::split(const Mat& src, Mat* mv) } } +namespace cv { + +static bool ocl_split( InputArray _m, OutputArrayOfArrays _mv ) +{ + int type = _m.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + + String dstargs, dstdecl, processelem; + for (int i = 0; i < cn; ++i) + { + dstargs += format("DECLARE_DST_PARAM(%d)", i); + dstdecl += format("DECLARE_DATA(%d)", i); + processelem += format("PROCESS_ELEM(%d)", i); + } + + ocl::Kernel k("split", ocl::core::split_merge_oclsrc, + format("-D T=%s -D OP_SPLIT -D cn=%d -D DECLARE_DST_PARAMS=%s " + "-D DECLARE_DATA_N=%s -D PROCESS_ELEMS_N=%s", + ocl::memopTypeToStr(depth), cn, dstargs.c_str(), + dstdecl.c_str(), processelem.c_str())); + if (k.empty()) + return false; + + Size size = _m.size(); + std::vector & dst = *(std::vector *)_mv.getObj(); + dst.resize(cn); + for (int i = 0; i < cn; ++i) + dst[i].create(size, depth); + + int argidx = k.set(0, ocl::KernelArg::ReadOnly(_m.getUMat())); + for (int i = 0; i < cn; ++i) + argidx = k.set(argidx, ocl::KernelArg::WriteOnlyNoSize(dst[i])); + + size_t globalsize[2] = { size.width, size.height }; + return k.run(2, globalsize, NULL, false); +} + +} + void cv::split(InputArray _m, OutputArrayOfArrays _mv) { + if (ocl::useOpenCL() && _m.dims() <= 2 && _mv.isUMatVector() && + ocl_split(_m, _mv)) + return; + Mat m = _m.getMat(); if( m.empty() ) { @@ -362,10 +404,6 @@ static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst ) int type = src[0].type(), depth = CV_MAT_DEPTH(type); Size size = src[0].size(); - bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; - - if (doubleSupport && depth == CV_64F) - return false; size_t srcsize = src.size(); for (size_t i = 0; i < srcsize; ++i) @@ -390,7 +428,7 @@ static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst ) if (k.empty()) return false; - _dst.create(size, CV_MAKE_TYPE(depth, srcsize)); + _dst.create(size, CV_MAKE_TYPE(depth, (int)srcsize)); UMat dst = _dst.getUMat(); int argidx = 0; diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 5fb0d35760..f733dd11fb 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -1893,7 +1893,7 @@ Context2& Context2::getDefault() // First, try to retrieve existing context of the same type. // In its turn, Platform::getContext() may call Context2::create() // if there is no such context. - ctx.create(Device::TYPE_CPU); + ctx.create(Device::TYPE_ACCELERATOR); if(!ctx.p) ctx.create(Device::TYPE_DGPU); if(!ctx.p) @@ -2189,13 +2189,8 @@ int Kernel::set(int i, const void* value, size_t sz) CV_Assert(i >= 0); if( i == 0 ) p->cleanupUMats(); - cl_int retval; - if( !p || !p->handle || (retval = clSetKernelArg(p->handle, (cl_uint)i, sz, value)) < 0 ) - { - printf("%d\n", retval); + if( !p || !p->handle || clSetKernelArg(p->handle, (cl_uint)i, sz, value) < 0 ) return -1; - } - printf("%d\n", retval); return i+1; } @@ -2206,7 +2201,6 @@ int Kernel::set(int i, const UMat& m) int Kernel::set(int i, const KernelArg& arg) { - printf("Setting to index %d\n", i); CV_Assert( i >= 0 ); if( !p || !p->handle ) return -1; @@ -2220,21 +2214,20 @@ int Kernel::set(int i, const KernelArg& arg) cl_mem h = (cl_mem)arg.m->handle(accessFlags); if (ptronly) - printf("%d\n", clSetKernelArg(p->handle, (cl_uint)i++, sizeof(h), &h)); + clSetKernelArg(p->handle, (cl_uint)i++, sizeof(h), &h); else if( arg.m->dims <= 2 ) { UMat2D u2d(*arg.m); - printf("setting ... \n"); - printf("%d\n", clSetKernelArg(p->handle, (cl_uint)i, sizeof(h), &h)); - printf("%d\n", clSetKernelArg(p->handle, (cl_uint)(i+1), sizeof(u2d.step), &u2d.step)); - printf("%d\n", clSetKernelArg(p->handle, (cl_uint)(i+2), sizeof(u2d.offset), &u2d.offset)); + clSetKernelArg(p->handle, (cl_uint)i, sizeof(h), &h); + clSetKernelArg(p->handle, (cl_uint)(i+1), sizeof(u2d.step), &u2d.step); + clSetKernelArg(p->handle, (cl_uint)(i+2), sizeof(u2d.offset), &u2d.offset); i += 3; if( !(arg.flags & KernelArg::NO_SIZE) ) { int cols = u2d.cols*arg.wscale; - printf("%d\n", clSetKernelArg(p->handle, (cl_uint)i, sizeof(u2d.rows), &u2d.rows)); - printf("%d\n", clSetKernelArg(p->handle, (cl_uint)(i+1), sizeof(cols), &cols)); + clSetKernelArg(p->handle, (cl_uint)i, sizeof(u2d.rows), &u2d.rows); + clSetKernelArg(p->handle, (cl_uint)(i+1), sizeof(cols), &cols); i += 2; } } diff --git a/modules/core/src/opencl/split_merge.cl b/modules/core/src/opencl/split_merge.cl index 2fd7b515cc..d2462750ce 100644 --- a/modules/core/src/opencl/split_merge.cl +++ b/modules/core/src/opencl/split_merge.cl @@ -65,16 +65,21 @@ __kernel void merge(DECLARE_SRC_PARAMS_N #elif defined OP_SPLIT -__kernel void set(__global uchar* dstptr, int dststep, int dstoffset, - int rows, int cols, dstT value ) +#define DECLARE_DST_PARAM(index) , __global uchar * dst##index##ptr, int dst##index##_step, int dst##index##_offset +#define DECLARE_DATA(index) __global T * dst##index = \ + (__global T *)(dst##index##ptr + mad24(y, dst##index##_step, x * (int)sizeof(T) + dst##index##_offset)); +#define PROCESS_ELEM(index) dst##index[0] = src[index]; + +__kernel void split(__global uchar* srcptr, int src_step, int src_offset, int rows, int cols DECLARE_DST_PARAMS) { int x = get_global_id(0); int y = get_global_id(1); if (x < cols && y < rows) { - int dst_index = mad24(y, dststep, x*(int)sizeof(dstT) + dstoffset); - *(__global dstT*)(dstptr + dst_index) = value; + DECLARE_DATA_N + __global const T * src = (__global const T *)(srcptr + mad24(y, src_step, x * cn * (int)sizeof(T) + src_offset)); + PROCESS_ELEMS_N } } diff --git a/modules/core/test/ocl/test_arithm.cpp b/modules/core/test/ocl/test_arithm.cpp index 9ef0d21313..844be7bdf2 100644 --- a/modules/core/test/ocl/test_arithm.cpp +++ b/modules/core/test/ocl/test_arithm.cpp @@ -42,6 +42,8 @@ #include "test_precomp.hpp" #include "opencv2/ts/ocl_test.hpp" +#ifdef HAVE_OPENCL + namespace cvtest { namespace ocl { @@ -1034,3 +1036,5 @@ OCL_INSTANTIATE_TEST_CASE_P(Arithm, Magnitude, Combine(::testing::Values(CV_32F, OCL_INSTANTIATE_TEST_CASE_P(Arithm, Flip, Combine(Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F), Values(1, 2, 3, 4), Bool())); } } // namespace cvtest::ocl + +#endif // HAVE_OPENCL diff --git a/modules/core/test/ocl/test_split_merge.cpp b/modules/core/test/ocl/test_split_merge.cpp index 70ba2d5020..224963cd24 100644 --- a/modules/core/test/ocl/test_split_merge.cpp +++ b/modules/core/test/ocl/test_split_merge.cpp @@ -47,6 +47,8 @@ #include "test_precomp.hpp" #include "opencv2/ts/ocl_test.hpp" +#ifdef HAVE_OPENCL + namespace cvtest { namespace ocl { @@ -69,11 +71,12 @@ PARAM_TEST_CASE(MergeTestBase, MatDepth, Channels, bool) depth = GET_PARAM(0); cn = GET_PARAM(1); use_roi = GET_PARAM(2); + + CV_Assert(cn >= 1 && cn <= 4); } - virtual void random_roi() + void random_roi() { - CV_Assert(cn >= 1 && cn <= 4); Size roiSize = randomSize(1, MAX_VALUE); { @@ -130,72 +133,91 @@ OCL_TEST_P(Merge, Accuracy) } } -//PARAM_TEST_CASE(SplitTestBase, MatType, int, bool) -//{ -// int type; -// int channels; -// bool use_roi; +PARAM_TEST_CASE(SplitTestBase, MatType, Channels, bool) +{ + int depth, cn; + bool use_roi; -// cv::Mat src, src_roi; -// cv::Mat dst[MAX_CHANNELS], dst_roi[MAX_CHANNELS]; + TEST_DECLARE_INPUT_PARAMETER(src) + TEST_DECLARE_OUTPUT_PARAMETER(dst1) + TEST_DECLARE_OUTPUT_PARAMETER(dst2) + TEST_DECLARE_OUTPUT_PARAMETER(dst3) + TEST_DECLARE_OUTPUT_PARAMETER(dst4) -// cv::ocl::oclMat gsrc_whole, gsrc_roi; -// cv::ocl::oclMat gdst_whole[MAX_CHANNELS], gdst_roi[MAX_CHANNELS]; + std::vector dst_roi, dst; + std::vector udst_roi, udst; -// virtual void SetUp() -// { -// type = GET_PARAM(0); -// channels = GET_PARAM(1); -// use_roi = GET_PARAM(2); -// } + virtual void SetUp() + { + depth = GET_PARAM(0); + cn = GET_PARAM(1); + use_roi = GET_PARAM(2); -// void random_roi() -// { -// Size roiSize = randomSize(1, MAX_VALUE); -// Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); -// randomSubMat(src, src_roi, roiSize, srcBorder, CV_MAKETYPE(type, channels), 0, 256); -// generateOclMat(gsrc_whole, gsrc_roi, src, roiSize, srcBorder); + CV_Assert(cn >= 1 && cn <= 4); + } -// for (int i = 0; i < channels; ++i) -// { -// Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); -// randomSubMat(dst[i], dst_roi[i], roiSize, dstBorder, CV_MAKETYPE(type, 1), 5, 16); -// generateOclMat(gdst_whole[i], gdst_roi[i], dst[i], roiSize, dstBorder); -// } -// } -//}; + void random_roi() + { + Size roiSize = randomSize(1, MAX_VALUE); + Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, CV_MAKE_TYPE(depth, cn), 5, 16); -//struct Split : SplitTestBase {}; + { + Border dst1Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst1, dst1_roi, roiSize, dst1Border, depth, 2, 11); -//#ifdef ANDROID -//// NOTE: The test fail on Android is the top of the iceberg only -//// The real fail reason is memory access vialation somewhere else -//OCL_TEST_P(Split, DISABLED_Accuracy) -//#else -//OCL_TEST_P(Split, Accuracy) -//#endif -//{ -// for(int j = 0; j < LOOP_TIMES; j++) -// { -// random_roi(); + Border dst2Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst2, dst2_roi, roiSize, dst2Border, depth, -1540, 1740); -// cv::split(src_roi, dst_roi); -// cv::ocl::split(gsrc_roi, gdst_roi); + Border dst3Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst3, dst3_roi, roiSize, dst3Border, depth, -1540, 1740); -// for (int i = 0; i < channels; ++i) -// { -// EXPECT_MAT_NEAR(dst[i], gdst_whole[i], 0.0); -// EXPECT_MAT_NEAR(dst_roi[i], gdst_roi[i], 0.0); -// } -// } -//} + Border dst4Border = randomBorder(0, use_roi ? MAX_VALUE : 0); + randomSubMat(dst4, dst4_roi, roiSize, dst4Border, depth, -1540, 1740); + } + UMAT_UPLOAD_INPUT_PARAMETER(src) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst1) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst2) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst3) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst4) + + dst_roi.push_back(dst1_roi), udst_roi.push_back(udst1_roi), + dst.push_back(dst1), udst.push_back(udst1); + if (cn >= 2) + dst_roi.push_back(dst2_roi), udst_roi.push_back(udst2_roi), + dst.push_back(dst2), udst.push_back(udst2); + if (cn >= 3) + dst_roi.push_back(dst3_roi), udst_roi.push_back(udst3_roi), + dst.push_back(dst3), udst.push_back(udst3); + if (cn >= 4) + dst_roi.push_back(dst4_roi), udst_roi.push_back(udst4_roi), + dst.push_back(dst4), udst.push_back(udst4); + } +}; + +typedef SplitTestBase Split; + +OCL_TEST_P(Split, Accuracy) +{ + for (int j = 0; j < test_loop_times; j++) + { + random_roi(); + + OCL_OFF(cv::split(src_roi, dst_roi)); + OCL_ON(cv::split(usrc_roi, udst_roi)); + + for (int i = 0; i < cn; ++i) + { + EXPECT_MAT_NEAR(dst[i], udst[i], 0.0); + EXPECT_MAT_NEAR(dst_roi[i], udst_roi[i], 0.0); + } + } +} OCL_INSTANTIATE_TEST_CASE_P(SplitMerge, Merge, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); - - -//INSTANTIATE_TEST_CASE_P(SplitMerge, Split , Combine( -// Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F), Values(1, 2, 3, 4), Bool())); - +OCL_INSTANTIATE_TEST_CASE_P(SplitMerge, Split, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool())); } } // namespace cvtest::ocl + +#endif // HAVE_OPENCL From 29ba7730ed6664ff9d52889eba376e97719df035 Mon Sep 17 00:00:00 2001 From: Vladimir Bystricky Date: Mon, 9 Dec 2013 10:45:23 +0400 Subject: [PATCH 87/97] Add ocl version of filter2D to the module img_proc --- modules/imgproc/src/filter.cpp | 186 ++++++++++ modules/imgproc/src/opencl/filter2D.cl | 377 +++++++++++++++++++++ modules/imgproc/test/ocl/test_filter2d.cpp | 138 ++++++++ 3 files changed, 701 insertions(+) create mode 100644 modules/imgproc/src/opencl/filter2D.cl create mode 100644 modules/imgproc/test/ocl/test_filter2d.cpp diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index fbf1de2479..80a9584165 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -41,6 +41,7 @@ //M*/ #include "precomp.hpp" +#include "opencl_kernels.hpp" /****************************************************************************************\ Base Image Filter @@ -3115,6 +3116,187 @@ template struct Filter2D : public BaseFi } +namespace cv +{ + +#define DIVUP(total, grain) (((total) + (grain) - 1) / (grain)) +#define ROUNDUP(sz, n) ((sz) + (n) - 1 - (((sz) + (n) - 1) % (n))) + +// prepare kernel: transpose and make double rows (+align). Returns size of aligned row +// Samples: +// a b c +// Input: d e f +// g h i +// Output, last two zeros is the alignment: +// a d g a d g 0 0 +// b e h b e h 0 0 +// c f i c f i 0 0 +template +static int _prepareKernelFilter2D(std::vector& data, const Mat &kernel) +{ + Mat _kernel; kernel.convertTo(_kernel, DataDepth::value); + int size_y_aligned = ROUNDUP(kernel.rows * 2, 4); + data.clear(); data.resize(size_y_aligned * kernel.cols, 0); + for (int x = 0; x < kernel.cols; x++) + { + for (int y = 0; y < kernel.rows; y++) + { + data[x * size_y_aligned + y] = _kernel.at(y, x); + data[x * size_y_aligned + y + kernel.rows] = _kernel.at(y, x); + } + } + return size_y_aligned; +} + +bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth, + InputArray _kernel, Point anchor, + double delta, int borderType ) +{ + if (abs(delta) > FLT_MIN) + return false; + + int type = _src.type(); + int cn = CV_MAT_CN(type); + if ((1 != cn) && (2 != cn) && (4 != cn)) + return false;//TODO + + int sdepth = CV_MAT_DEPTH(type); + Size ksize = _kernel.size(); + if( anchor.x < 0 ) + anchor.x = ksize.width / 2; + if( anchor.y < 0 ) + anchor.y = ksize.height / 2; + if( ddepth < 0 ) + ddepth = sdepth; + else if (ddepth != sdepth) + return false; + + bool isIsolatedBorder = (borderType & BORDER_ISOLATED) != 0; + bool useDouble = (CV_64F == sdepth); + const cv::ocl::Device &device = cv::ocl::Device::getDefault(); + int doubleFPConfig = device.doubleFPConfig(); + if (useDouble && (0 == doubleFPConfig)) + return false; + + const char* btype = NULL; + switch (borderType & ~BORDER_ISOLATED) + { + case BORDER_CONSTANT: + btype = "BORDER_CONSTANT"; + break; + case BORDER_REPLICATE: + btype = "BORDER_REPLICATE"; + break; + case BORDER_REFLECT: + btype = "BORDER_REFLECT"; + break; + case BORDER_WRAP: + return false; + case BORDER_REFLECT101: + btype = "BORDER_REFLECT_101"; + break; + } + + cv::Mat kernelMat = _kernel.getMat(); + std::vector kernelMatDataFloat; + std::vector kernelMatDataDouble; + int kernel_size_y2_aligned = useDouble ? + _prepareKernelFilter2D(kernelMatDataDouble, kernelMat) + : _prepareKernelFilter2D(kernelMatDataFloat, kernelMat); + + + cv::Size sz = _src.size(); + size_t globalsize[2] = {sz.width, sz.height}; + size_t localsize[2] = {0, 1}; + + ocl::Kernel kernel; + + size_t maxWorkItemSizes[32]; device.maxWorkItemSizes(maxWorkItemSizes); + size_t tryWorkItems = maxWorkItemSizes[0]; + for (;;) + { + size_t BLOCK_SIZE = tryWorkItems; + while (BLOCK_SIZE > 32 && BLOCK_SIZE >= (size_t)ksize.width * 2 && BLOCK_SIZE > (size_t)sz.width * 2) + BLOCK_SIZE /= 2; +#if 1 // TODO Mode with several blocks requires a much more VGPRs, so this optimization is not actual for the current devices + size_t BLOCK_SIZE_Y = 1; +#else + size_t BLOCK_SIZE_Y = 8; // TODO Check heuristic value on devices + while (BLOCK_SIZE_Y < BLOCK_SIZE / 8 && BLOCK_SIZE_Y * src.clCxt->getDeviceInfo().maxComputeUnits * 32 < (size_t)src.rows) + BLOCK_SIZE_Y *= 2; +#endif + + if ((size_t)ksize.width > BLOCK_SIZE) + return false; + + int requiredTop = anchor.y; + int requiredLeft = (int)BLOCK_SIZE; // not this: anchor.x; + int requiredBottom = ksize.height - 1 - anchor.y; + int requiredRight = (int)BLOCK_SIZE; // not this: ksize.width - 1 - anchor.x; + int h = sz.height; + int w = sz.width; + bool extra_extrapolation = h < requiredTop || h < requiredBottom || w < requiredLeft || w < requiredRight; + + if ((w < ksize.width) || (h < ksize.height)) + return false; + + char build_options[1024]; + sprintf(build_options, "-D LOCAL_SIZE=%d -D BLOCK_SIZE_Y=%d -D DATA_DEPTH=%d -D DATA_CHAN=%d -D USE_DOUBLE=%d " + "-D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d -D KERNEL_SIZE_Y2_ALIGNED=%d " + "-D %s -D %s -D %s", + (int)BLOCK_SIZE, (int)BLOCK_SIZE_Y, + sdepth, cn, useDouble ? 1 : 0, + anchor.x, anchor.y, ksize.width, ksize.height, kernel_size_y2_aligned, + btype, + extra_extrapolation ? "EXTRA_EXTRAPOLATION" : "NO_EXTRA_EXTRAPOLATION", + isIsolatedBorder ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED"); + + localsize[0] = BLOCK_SIZE; + globalsize[0] = DIVUP(sz.width, BLOCK_SIZE - (ksize.width - 1)) * BLOCK_SIZE; + globalsize[1] = DIVUP(sz.height, BLOCK_SIZE_Y); + + cv::String errmsg; + if (!kernel.create("filter2D", cv::ocl::imgproc::filter2D_oclsrc, build_options)) + return false; + size_t kernelWorkGroupSize = kernel.workGroupSize(); + if (localsize[0] <= kernelWorkGroupSize) + break; + if (BLOCK_SIZE < kernelWorkGroupSize) + return false; + tryWorkItems = kernelWorkGroupSize; + } + + _dst.create(sz, CV_MAKETYPE(ddepth, cn)); + UMat dst = _dst.getUMat(); + UMat src = _src.getUMat(); + + int idxArg = 0; + idxArg = kernel.set(idxArg, ocl::KernelArg::ReadOnlyNoSize(src)); + idxArg = kernel.set(idxArg, ocl::KernelArg::WriteOnly(dst)); + float borderValue[4] = {0, 0, 0, 0}; + double borderValueDouble[4] = {0, 0, 0, 0}; + if ((borderType & ~BORDER_ISOLATED) == BORDER_CONSTANT) + { + int cnocl = (3 == cn) ? 4 : cn; + if (useDouble) + idxArg = kernel.set(idxArg, (void *)&borderValueDouble[0], sizeof(double) * cnocl); + else + idxArg = kernel.set(idxArg, (void *)&borderValue[0], sizeof(float) * cnocl); + } + if (useDouble) + { + UMat kernalDataUMat(kernelMatDataDouble, true); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(kernalDataUMat)); + } + else + { + UMat kernalDataUMat(kernelMatDataFloat, true); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(kernalDataUMat)); + } + return kernel.run(2, globalsize, localsize, true); +} +} + cv::Ptr cv::getLinearFilter(int srcType, int dstType, InputArray filter_kernel, Point anchor, double delta, int bits) @@ -3230,6 +3412,10 @@ void cv::filter2D( InputArray _src, OutputArray _dst, int ddepth, InputArray _kernel, Point anchor, double delta, int borderType ) { + bool use_opencl = ocl::useOpenCL() && _dst.isUMat(); + if( use_opencl && ocl_filter2D(_src, _dst, ddepth, _kernel, anchor, delta, borderType)) + return; + Mat src = _src.getMat(), kernel = _kernel.getMat(); if( ddepth < 0 ) diff --git a/modules/imgproc/src/opencl/filter2D.cl b/modules/imgproc/src/opencl/filter2D.cl new file mode 100644 index 0000000000..1225be93fc --- /dev/null +++ b/modules/imgproc/src/opencl/filter2D.cl @@ -0,0 +1,377 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do 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, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors as is and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifdef BORDER_REPLICATE +//BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh +#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? (l_edge) : (i)) +#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? (r_edge)-1 : (addr)) +#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? (t_edge) :(i)) +#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? (b_edge)-1 :(addr)) +#endif + +#ifdef BORDER_REFLECT +//BORDER_REFLECT: fedcba|abcdefgh|hgfedcb +#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? -(i)-1 : (i)) +#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? -(i)-1+((r_edge)<<1) : (addr)) +#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? -(i)-1 : (i)) +#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? -(i)-1+((b_edge)<<1) : (addr)) +#endif + +#ifdef BORDER_REFLECT_101 +//BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba +#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? -(i) : (i)) +#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? -(i)-2+((r_edge)<<1) : (addr)) +#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? -(i) : (i)) +#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? -(i)-2+((b_edge)<<1) : (addr)) +#endif + +//blur function does not support BORDER_WRAP +#ifdef BORDER_WRAP +//BORDER_WRAP: cdefgh|abcdefgh|abcdefg +#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? (i)+(r_edge) : (i)) +#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? (i)-(r_edge) : (addr)) +#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? (i)+(b_edge) : (i)) +#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? (i)-(b_edge) : (addr)) +#endif + +#ifdef EXTRA_EXTRAPOLATION // border > src image size +#ifdef BORDER_CONSTANT +// None +#elif defined BORDER_REPLICATE +#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \ + { \ + x = max(min(x, maxX - 1), minX); \ + y = max(min(y, maxY - 1), minY); \ + } +#elif defined BORDER_WRAP +#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \ + { \ + if (x < minX) \ + x -= ((x - maxX + 1) / maxX) * maxX; \ + if (x >= maxX) \ + x %= maxX; \ + if (y < minY) \ + y -= ((y - maxY + 1) / maxY) * maxY; \ + if (y >= maxY) \ + y %= maxY; \ + } +#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT_101) +#define EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, delta) \ + { \ + if (maxX - minX == 1) \ + x = minX; \ + else \ + do \ + { \ + if (x < minX) \ + x = -(x - minX) - 1 + delta; \ + else \ + x = maxX - 1 - (x - maxX) - delta; \ + } \ + while (x >= maxX || x < minX); \ + \ + if (maxY - minY == 1) \ + y = minY; \ + else \ + do \ + { \ + if (y < minY) \ + y = -(y - minY) - 1 + delta; \ + else \ + y = maxY - 1 - (y - maxY) - delta; \ + } \ + while (y >= maxY || y < minY); \ + } +#ifdef BORDER_REFLECT +#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, 0) +#elif defined(BORDER_REFLECT_101) +#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, 1) +#endif +#else +#error No extrapolation method +#endif +#else +#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \ + { \ + int _row = y - minY, _col = x - minX; \ + _row = ADDR_H(_row, 0, maxY - minY); \ + _row = ADDR_B(_row, maxY - minY, _row); \ + y = _row + minY; \ + \ + _col = ADDR_L(_col, 0, maxX - minX); \ + _col = ADDR_R(_col, maxX - minX, _col); \ + x = _col + minX; \ + } +#endif + +#if USE_DOUBLE +#ifdef cl_amd_fp64 +#pragma OPENCL EXTENSION cl_amd_fp64:enable +#elif defined (cl_khr_fp64) +#pragma OPENCL EXTENSION cl_khr_fp64:enable +#endif +#define FPTYPE double +#define CONVERT_TO_FPTYPE CAT(convert_double, VEC_SIZE) +#else +#define FPTYPE float +#define CONVERT_TO_FPTYPE CAT(convert_float, VEC_SIZE) +#endif + +#if DATA_DEPTH == 0 +#define BASE_TYPE uchar +#elif DATA_DEPTH == 1 +#define BASE_TYPE char +#elif DATA_DEPTH == 2 +#define BASE_TYPE ushort +#elif DATA_DEPTH == 3 +#define BASE_TYPE short +#elif DATA_DEPTH == 4 +#define BASE_TYPE int +#elif DATA_DEPTH == 5 +#define BASE_TYPE float +#elif DATA_DEPTH == 6 +#define BASE_TYPE double +#else +#error data_depth +#endif + +#define __CAT(x, y) x##y +#define CAT(x, y) __CAT(x, y) + +#define uchar1 uchar +#define char1 char +#define ushort1 ushort +#define short1 short +#define int1 int +#define float1 float +#define double1 double + +#define convert_uchar1_sat_rte convert_uchar_sat_rte +#define convert_char1_sat_rte convert_char_sat_rte +#define convert_ushort1_sat_rte convert_ushort_sat_rte +#define convert_short1_sat_rte convert_short_sat_rte +#define convert_int1_sat_rte convert_int_sat_rte +#define convert_float1 +#define convert_double1 + +#if DATA_DEPTH == 5 || DATA_DEPTH == 6 +#define CONVERT_TO_TYPE CAT(CAT(convert_, BASE_TYPE), VEC_SIZE) +#else +#define CONVERT_TO_TYPE CAT(CAT(CAT(convert_, BASE_TYPE), VEC_SIZE), _sat_rte) +#endif + +#define VEC_SIZE DATA_CHAN + +#define VEC_TYPE CAT(BASE_TYPE, VEC_SIZE) +#define TYPE VEC_TYPE + +#define SCALAR_TYPE CAT(FPTYPE, VEC_SIZE) + +#define INTERMEDIATE_TYPE CAT(FPTYPE, VEC_SIZE) + +struct RectCoords +{ + int x1, y1, x2, y2; +}; + +//#define DEBUG +#ifdef DEBUG +#define DEBUG_ONLY(x) x +#define ASSERT(condition) do { if (!(condition)) { printf("BUG in boxFilter kernel (global=%d,%d): " #condition "\n", get_global_id(0), get_global_id(1)); } } while (0) +#else +#define DEBUG_ONLY(x) (void)0 +#define ASSERT(condition) (void)0 +#endif + + +inline INTERMEDIATE_TYPE readSrcPixel(int2 pos, __global const uchar* srcptr, int srcstep, int srcoffset, const struct RectCoords srcCoords +#ifdef BORDER_CONSTANT + , SCALAR_TYPE borderValue +#endif + ) +{ +#ifdef BORDER_ISOLATED + if(pos.x >= srcCoords.x1 && pos.y >= srcCoords.y1 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) +#else + if(pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) +#endif + { + //__global TYPE* ptr = (__global TYPE*)((__global char*)src + pos.x * sizeof(TYPE) + pos.y * srcStepBytes); + __global TYPE* ptr = (__global TYPE*)(srcptr + pos.y * srcstep + srcoffset + pos.x * sizeof(TYPE)); + return CONVERT_TO_FPTYPE(*ptr); + } + else + { +#ifdef BORDER_CONSTANT + return borderValue; +#else + int selected_col = pos.x; + int selected_row = pos.y; + + EXTRAPOLATE(selected_col, selected_row, +#ifdef BORDER_ISOLATED + srcCoords.x1, srcCoords.y1, +#else + 0, 0, +#endif + srcCoords.x2, srcCoords.y2 + ); + + // debug border mapping + //printf("pos=%d,%d --> %d, %d\n", pos.x, pos.y, selected_col, selected_row); + + pos = (int2)(selected_col, selected_row); + if(pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) + { + //__global TYPE* ptr = (__global TYPE*)((__global char*)src + pos.x * sizeof(TYPE) + pos.y * srcStepBytes); + __global TYPE* ptr = (__global TYPE*)(srcptr + pos.y * srcstep + srcoffset + pos.x * sizeof(TYPE)); + return CONVERT_TO_FPTYPE(*ptr); + } + else + { + // for debug only + DEBUG_ONLY(printf("BUG in boxFilter kernel\n")); + return (FPTYPE)(0.0f); + } +#endif + } +} + +// INPUT PARAMETER: BLOCK_SIZE_Y (via defines) + +__kernel +__attribute__((reqd_work_group_size(LOCAL_SIZE, 1, 1))) +void filter2D(__global const uchar* srcptr, int srcstep, int srcoffset, + __global uchar* dstptr, int dststep, int dstoffset, + int rows, int cols, +#ifdef BORDER_CONSTANT + SCALAR_TYPE borderValue, +#endif + __constant FPTYPE* kernelData // transposed: [KERNEL_SIZE_X][KERNEL_SIZE_Y2_ALIGNED] + ) +{ + const struct RectCoords srcCoords = {0, 0, cols, rows}; // for non-isolated border: offsetX, offsetY, wholeX, wholeY + const struct RectCoords dstCoords = {0, 0, cols, rows}; + + const int local_id = get_local_id(0); + const int x = local_id + (LOCAL_SIZE - (KERNEL_SIZE_X - 1)) * get_group_id(0) - ANCHOR_X; + const int y = get_global_id(1) * BLOCK_SIZE_Y; + + INTERMEDIATE_TYPE data[KERNEL_SIZE_Y]; + __local INTERMEDIATE_TYPE sumOfCols[LOCAL_SIZE]; + + int2 srcPos = (int2)(srcCoords.x1 + x, srcCoords.y1 + y - ANCHOR_Y); + + int2 pos = (int2)(dstCoords.x1 + x, dstCoords.y1 + y); + __global TYPE* dstPtr = (__global TYPE*)((__global char*)dstptr + pos.y * dststep + dstoffset + pos.x * sizeof(TYPE)); // Pointer can be out of bounds! + bool writeResult = (local_id >= ANCHOR_X && local_id < LOCAL_SIZE - (KERNEL_SIZE_X - 1 - ANCHOR_X) && + pos.x >= dstCoords.x1 && pos.x < dstCoords.x2); + +#if BLOCK_SIZE_Y > 1 + bool readAllpixels = true; + int sy_index = 0; // current index in data[] array + + dstCoords.y2 = min(dstCoords.y2, pos.y + BLOCK_SIZE_Y); + for (; + pos.y < dstCoords.y2; + pos.y++, + dstPtr = (__global TYPE*)((__global char*)dstptr + dststep)) +#endif + { + ASSERT(pos.y < dstCoords.y2); + + for ( +#if BLOCK_SIZE_Y > 1 + int sy = readAllpixels ? 0 : -1; sy < (readAllpixels ? KERNEL_SIZE_Y : 0); +#else + int sy = 0, sy_index = 0; sy < KERNEL_SIZE_Y; +#endif + sy++, srcPos.y++) + { + data[sy + sy_index] = readSrcPixel(srcPos, srcptr, srcstep, srcoffset, srcCoords +#ifdef BORDER_CONSTANT + , borderValue +#endif + ); + } + + INTERMEDIATE_TYPE total_sum = 0; + for (int sx = 0; sx < KERNEL_SIZE_X; sx++) + { + { + __constant FPTYPE* k = &kernelData[KERNEL_SIZE_Y2_ALIGNED * sx +#if BLOCK_SIZE_Y > 1 + + KERNEL_SIZE_Y - sy_index +#endif + ]; + INTERMEDIATE_TYPE tmp_sum = 0; + for (int sy = 0; sy < KERNEL_SIZE_Y; sy++) + { + tmp_sum += data[sy] * k[sy]; + } + + sumOfCols[local_id] = tmp_sum; + barrier(CLK_LOCAL_MEM_FENCE); + } + + int id = local_id + sx - ANCHOR_X; + if (id >= 0 && id < LOCAL_SIZE) + total_sum += sumOfCols[id]; + + barrier(CLK_LOCAL_MEM_FENCE); + } + + if (writeResult) + { + ASSERT(pos.y >= dstCoords.y1 && pos.y < dstCoords.y2); + *dstPtr = CONVERT_TO_TYPE(total_sum); + } + +#if BLOCK_SIZE_Y > 1 + readAllpixels = false; +#if BLOCK_SIZE_Y > KERNEL_SIZE_Y + sy_index = (sy_index + 1 <= KERNEL_SIZE_Y) ? sy_index + 1 : 1; +#else + sy_index++; +#endif +#endif // BLOCK_SIZE_Y == 1 + } +} diff --git a/modules/imgproc/test/ocl/test_filter2d.cpp b/modules/imgproc/test/ocl/test_filter2d.cpp new file mode 100644 index 0000000000..a3c3a23609 --- /dev/null +++ b/modules/imgproc/test/ocl/test_filter2d.cpp @@ -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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Copyright (C) 2010-2012, Multicoreware, 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" +#include "opencv2/ts/ocl_test.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +enum +{ + noType = -1, +}; + + +///////////////////////////////////////////////////////////////////////////////////////////////// +// Filter2D +PARAM_TEST_CASE(Filter2D, MatDepth, Channels, BorderType, bool) +{ + static const int kernelMinSize = 1; + static const int kernelMaxSize = 10; + + int type; + Size ksize; + Size dsize; + Point anchor; + int borderType; + bool useRoi; + Mat kernel; + + TEST_DECLARE_INPUT_PARAMETER(src) + TEST_DECLARE_OUTPUT_PARAMETER(dst) + + virtual void SetUp() + { + type = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1)); + borderType = GET_PARAM(2); + useRoi = GET_PARAM(3); + } + + void random_roi() + { + dsize = randomSize(1, MAX_VALUE); + + Size ksize = randomSize(kernelMinSize, kernelMaxSize); + kernel = randomMat(ksize, CV_MAKE_TYPE(((CV_64F == CV_MAT_DEPTH(type)) ? CV_64F : CV_32F), 1), -MAX_VALUE, MAX_VALUE); + + Size roiSize = randomSize(1, MAX_VALUE); + Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE); + + Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(dst, dst_roi, dsize, dstBorder, type, -MAX_VALUE, MAX_VALUE); + + anchor.x = anchor.y = -1; + + UMAT_UPLOAD_INPUT_PARAMETER(src) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst) + } + + void Near(double threshold = 0.0) + { + EXPECT_MAT_NEAR(dst, udst, threshold); + EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold); + } +}; + +OCL_TEST_P(Filter2D, Mat) +{ + for (int j = 0; j < test_loop_times; j++) + { + random_roi(); + + OCL_OFF(cv::filter2D(src_roi, dst_roi, -1, kernel, anchor, 0.0, borderType)); + OCL_ON(cv::filter2D(usrc_roi, udst_roi, -1, kernel, anchor, 0.0, borderType)); + + Near(1.0); + } +} + + +OCL_INSTANTIATE_TEST_CASE_P(ImageProc, Filter2D, + Combine( + Values(CV_8U, CV_16U, CV_16S, CV_32F, CV_64F), + Values(1, 2, 4), + Values((BorderType)BORDER_CONSTANT, + (BorderType)BORDER_REPLICATE, + (BorderType)BORDER_REFLECT, + (BorderType)BORDER_REFLECT_101), + Bool()) + ); + + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL From 179a43ef63745d5d4d58734324bf54202ccb2158 Mon Sep 17 00:00:00 2001 From: Vladimir Bystricky Date: Mon, 9 Dec 2013 11:10:48 +0400 Subject: [PATCH 88/97] Fix build errors on Linux system --- modules/imgproc/src/filter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 80a9584165..832b0d0381 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -3148,7 +3148,7 @@ static int _prepareKernelFilter2D(std::vector& data, const Mat &kernel) return size_y_aligned; } -bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth, +static bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth, InputArray _kernel, Point anchor, double delta, int borderType ) { From 8d8f5665f1a015e761811875df9937942e3effaf Mon Sep 17 00:00:00 2001 From: Vladimir Bystricky Date: Mon, 9 Dec 2013 11:31:55 +0400 Subject: [PATCH 89/97] Fix build errors on Linux system --- modules/imgproc/test/ocl/test_filter2d.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/imgproc/test/ocl/test_filter2d.cpp b/modules/imgproc/test/ocl/test_filter2d.cpp index a3c3a23609..ca1450952c 100644 --- a/modules/imgproc/test/ocl/test_filter2d.cpp +++ b/modules/imgproc/test/ocl/test_filter2d.cpp @@ -63,7 +63,6 @@ PARAM_TEST_CASE(Filter2D, MatDepth, Channels, BorderType, bool) static const int kernelMaxSize = 10; int type; - Size ksize; Size dsize; Point anchor; int borderType; From 93c6fe66ce7ab72e1c80e70eccad54714d3010fc Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 9 Dec 2013 16:03:25 +0400 Subject: [PATCH 90/97] added cv::bilateralFilter to T-API --- modules/imgproc/src/opencl/bilateral.cl | 59 ++++++++ modules/imgproc/src/smooth.cpp | 97 ++++++++++-- modules/imgproc/test/ocl/test_filters.cpp | 176 ++++++++++++++++++++++ 3 files changed, 321 insertions(+), 11 deletions(-) create mode 100644 modules/imgproc/src/opencl/bilateral.cl create mode 100644 modules/imgproc/test/ocl/test_filters.cpp diff --git a/modules/imgproc/src/opencl/bilateral.cl b/modules/imgproc/src/opencl/bilateral.cl new file mode 100644 index 0000000000..f459cfc850 --- /dev/null +++ b/modules/imgproc/src/opencl/bilateral.cl @@ -0,0 +1,59 @@ +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Rock Li, Rock.li@amd.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 materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors as is and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. + +__kernel void bilateral(__global const uchar * src, int src_step, int src_offset, + __global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols, + __constant float * color_weight, __constant float * space_weight, __constant int * space_ofs) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if (y < dst_rows && x < dst_cols) + { + int src_index = mad24(y + radius, src_step, x + radius + src_offset); + int dst_index = mad24(y, dst_step, x + dst_offset); + float sum = 0.f, wsum = 0.f; + int val0 = convert_int(src[src_index]); + + #pragma unroll + for (int k = 0; k < maxk; k++ ) + { + int val = convert_int(src[src_index + space_ofs[k]]); + float w = space_weight[k] * color_weight[abs(val - val0)]; + sum += (float)(val) * w; + wsum += w; + } + dst[dst_index] = convert_uchar_rtz(sum / wsum + 0.5f); + } +} diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 2e2eabf4e1..7ef850863f 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -41,6 +41,7 @@ //M*/ #include "precomp.hpp" +#include "opencl_kernels.hpp" /* * This file includes the code, contributed by Simon Perreault @@ -1914,19 +1915,91 @@ private: }; #endif +static bool ocl_bilateralFilter_8u(InputArray _src, OutputArray _dst, int d, + double sigma_color, double sigma_space, + int borderType) +{ + int type = _src.type(), cn = CV_MAT_CN(type); + int i, j, maxk, radius; + + if ( type != CV_8UC1 ) + return false; + + if (sigma_color <= 0) + sigma_color = 1; + if (sigma_space <= 0) + sigma_space = 1; + + double gauss_color_coeff = -0.5 / (sigma_color * sigma_color); + double gauss_space_coeff = -0.5 / (sigma_space * sigma_space); + + if ( d <= 0 ) + radius = cvRound(sigma_space * 1.5); + else + radius = d / 2; + radius = MAX(radius, 1); + d = radius * 2 + 1; + + UMat src = _src.getUMat(), dst = _dst.getUMat(), temp; + if (src.u == dst.u) + return false; + + copyMakeBorder(src, temp, radius, radius, radius, radius, borderType); + + std::vector _color_weight(cn * 256); + std::vector _space_weight(d * d); + std::vector _space_ofs(d * d); + float *color_weight = &_color_weight[0]; + float *space_weight = &_space_weight[0]; + int *space_ofs = &_space_ofs[0]; + + // initialize color-related bilateral filter coefficients + for( i = 0; i < 256 * cn; i++ ) + color_weight[i] = (float)std::exp(i * i * gauss_color_coeff); + + // initialize space-related bilateral filter coefficients + for( i = -radius, maxk = 0; i <= radius; i++ ) + for( j = -radius; j <= radius; j++ ) + { + double r = std::sqrt((double)i * i + (double)j * j); + if ( r > radius ) + continue; + space_weight[maxk] = (float)std::exp(r * r * gauss_space_coeff); + space_ofs[maxk++] = (int)(i * temp.step + j); + } + + ocl::Kernel k("bilateral", ocl::imgproc::bilateral_oclsrc, + format("-D radius=%d -D maxk=%d", radius, maxk)); + if (k.empty()) + return false; + + Mat mcolor_weight(1, cn * 256, CV_32FC1, color_weight); + Mat mspace_weight(1, d * d, CV_32FC1, space_weight); + Mat mspace_ofs(1, d * d, CV_32SC1, space_ofs); + UMat ucolor_weight, uspace_weight, uspace_ofs; + mcolor_weight.copyTo(ucolor_weight); + mspace_weight.copyTo(uspace_weight); + mspace_ofs.copyTo(uspace_ofs); + + k.args(ocl::KernelArg::ReadOnlyNoSize(temp), ocl::KernelArg::WriteOnly(dst), + ocl::KernelArg::PtrReadOnly(ucolor_weight), + ocl::KernelArg::PtrReadOnly(uspace_weight), + ocl::KernelArg::PtrReadOnly(uspace_ofs)); + + size_t globalsize[2] = { dst.cols, dst.rows }; + return k.run(2, globalsize, NULL, false); +} + static void bilateralFilter_8u( const Mat& src, Mat& dst, int d, double sigma_color, double sigma_space, int borderType ) { - int cn = src.channels(); int i, j, maxk, radius; Size size = src.size(); - CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_8UC3) && - src.type() == dst.type() && src.size() == dst.size() && - src.data != dst.data ); + CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_8UC3) && src.data != dst.data ); if( sigma_color <= 0 ) sigma_color = 1; @@ -1973,7 +2046,7 @@ bilateralFilter_8u( const Mat& src, Mat& dst, int d, { j = -radius; - for( ;j <= radius; j++ ) + for( ; j <= radius; j++ ) { double r = std::sqrt((double)i*i + (double)j*j); if( r > radius ) @@ -2184,9 +2257,7 @@ bilateralFilter_32f( const Mat& src, Mat& dst, int d, float len, scale_index; Size size = src.size(); - CV_Assert( (src.type() == CV_32FC1 || src.type() == CV_32FC3) && - src.type() == dst.type() && src.size() == dst.size() && - src.data != dst.data ); + CV_Assert( (src.type() == CV_32FC1 || src.type() == CV_32FC3) && src.data != dst.data ); if( sigma_color <= 0 ) sigma_color = 1; @@ -2267,9 +2338,13 @@ void cv::bilateralFilter( InputArray _src, OutputArray _dst, int d, double sigmaColor, double sigmaSpace, int borderType ) { - Mat src = _src.getMat(); - _dst.create( src.size(), src.type() ); - Mat dst = _dst.getMat(); + _dst.create( _src.size(), _src.type() ); + + if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() && + ocl_bilateralFilter_8u(_src, _dst, d, sigmaColor, sigmaSpace, borderType)) + return; + + Mat src = _src.getMat(), dst = _dst.getMat(); if( src.depth() == CV_8U ) bilateralFilter_8u( src, dst, d, sigmaColor, sigmaSpace, borderType ); diff --git a/modules/imgproc/test/ocl/test_filters.cpp b/modules/imgproc/test/ocl/test_filters.cpp new file mode 100644 index 0000000000..58d23e8358 --- /dev/null +++ b/modules/imgproc/test/ocl/test_filters.cpp @@ -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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Niko Li, newlife20080214@gmail.com +// Jia Haipeng, jiahaipeng95@gmail.com +// Zero Lin, Zero.Lin@amd.com +// Zhang Ying, zhangying913@gmail.com +// Yao Wang, bitwangyaoyao@gmail.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 materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including 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 "cvconfig.h" +#include "opencv2/ts/ocl_test.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +PARAM_TEST_CASE(FilterTestBase, MatType, + int, // kernel size + Size, // dx, dy + int, // border type + double, // optional parameter + bool) // roi or not +{ + int type, borderType, ksize; + Size size; + double param; + bool useRoi; + + TEST_DECLARE_INPUT_PARAMETER(src) + TEST_DECLARE_OUTPUT_PARAMETER(dst) + + virtual void SetUp() + { + type = GET_PARAM(0); + ksize = GET_PARAM(1); + size = GET_PARAM(2); + borderType = GET_PARAM(3); + param = GET_PARAM(4); + useRoi = GET_PARAM(5); + } + + void random_roi(int minSize = 1) + { + if (minSize == 0) + minSize = ksize; + + Size roiSize = randomSize(minSize, MAX_VALUE); + Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(src, src_roi, roiSize, srcBorder, type, 5, 256); + + Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(dst, dst_roi, roiSize, dstBorder, type, -60, 70); + + UMAT_UPLOAD_INPUT_PARAMETER(src) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst) + } + + void Near() + { + int depth = CV_MAT_DEPTH(type); + bool isFP = depth >= CV_32F; + + if (isFP) + Near(1e-6, true); + else + Near(1, false); + } + + void Near(double threshold, bool relative) + { + if (relative) + { + EXPECT_MAT_NEAR_RELATIVE(dst, udst, threshold); + EXPECT_MAT_NEAR_RELATIVE(dst_roi, udst_roi, threshold); + } + else + { + EXPECT_MAT_NEAR(dst, udst, threshold); + EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold); + } + } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Bilateral + +typedef FilterTestBase Bilateral; + +OCL_TEST_P(Bilateral, Mat) +{ + for (int j = 0; j < test_loop_times; j++) + { + random_roi(); + + double sigmacolor = rng.uniform(20, 100); + double sigmaspace = rng.uniform(10, 40); + + OCL_OFF(cv::bilateralFilter(src_roi, dst_roi, ksize, sigmacolor, sigmaspace, borderType)); + OCL_ON(cv::bilateralFilter(usrc_roi, udst_roi, ksize, sigmacolor, sigmaspace, borderType)); + + Near(); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define FILTER_BORDER_SET_NO_ISOLATED \ + Values((int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, (int)BORDER_WRAP, (int)BORDER_REFLECT_101/*, \ + (int)BORDER_CONSTANT|BORDER_ISOLATED, (int)BORDER_REPLICATE|BORDER_ISOLATED, \ + (int)BORDER_REFLECT|BORDER_ISOLATED, (int)BORDER_WRAP|BORDER_ISOLATED, \ + (int)BORDER_REFLECT_101|BORDER_ISOLATED*/) // WRAP and ISOLATED are not supported by cv:: version + +#define FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED \ + Values((int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, /*(int)BORDER_WRAP,*/ (int)BORDER_REFLECT_101/*, \ + (int)BORDER_CONSTANT|BORDER_ISOLATED, (int)BORDER_REPLICATE|BORDER_ISOLATED, \ + (int)BORDER_REFLECT|BORDER_ISOLATED, (int)BORDER_WRAP|BORDER_ISOLATED, \ + (int)BORDER_REFLECT_101|BORDER_ISOLATED*/) // WRAP and ISOLATED are not supported by cv:: version + +#define FILTER_DATATYPES Values(CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4, \ + CV_32FC1, CV_32FC3, CV_32FC4, \ + CV_64FC1, CV_64FC3, CV_64FC4) + +OCL_INSTANTIATE_TEST_CASE_P(Filter, Bilateral, Combine( + Values((MatType)CV_8UC1), + Values(5, 9), + Values(Size(0, 0)), // not used + FILTER_BORDER_SET_NO_ISOLATED, + Values(0.0), // not used + Bool())); + +} } // namespace cvtest::ocl + +#endif // HAVE_OPENCL From c9e6ed7a29969b2c1fe0d3e6b4eaf347a9926bf8 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Sun, 8 Dec 2013 23:16:17 +0400 Subject: [PATCH 91/97] added cv::blendLinear --- modules/imgproc/include/opencv2/imgproc.hpp | 3 + modules/imgproc/src/blend.cpp | 145 ++++++++++++++++++++ modules/imgproc/src/opencl/blend_linear.cl | 88 ++++++++++++ modules/imgproc/test/ocl/test_blend.cpp | 129 +++++++++++++++++ 4 files changed, 365 insertions(+) create mode 100644 modules/imgproc/src/blend.cpp create mode 100644 modules/imgproc/src/opencl/blend_linear.cl create mode 100644 modules/imgproc/test/ocl/test_blend.cpp diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 59f6ae01a9..8980f3a9cc 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -1512,6 +1512,9 @@ CV_EXPORTS Ptr createGeneralizedHoughBallard(); //! Detects position, traslation and rotation CV_EXPORTS Ptr createGeneralizedHoughGuil(); +//! Performs linear blending of two images +CV_EXPORTS void blendLinear(InputArray src1, InputArray src2, InputArray weights1, InputArray weights2, OutputArray dst); + } // cv #endif diff --git a/modules/imgproc/src/blend.cpp b/modules/imgproc/src/blend.cpp new file mode 100644 index 0000000000..91b261dfa6 --- /dev/null +++ b/modules/imgproc/src/blend.cpp @@ -0,0 +1,145 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do 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-2012, Multicoreware, Inc., all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Nathan, liujun@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 materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including 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 "opencl_kernels.hpp" + +namespace cv { + +template +class BlendLinearInvoker : + public ParallelLoopBody +{ +public: + BlendLinearInvoker(const Mat & _src1, const Mat & _src2, const Mat & _weights1, + const Mat & _weights2, Mat & _dst) : + src1(&_src1), src2(&_src2), weights1(&_weights1), weights2(&_weights2), dst(&_dst) + { + } + + virtual void operator() (const Range & range) const + { + int cn = src1->channels(), width = src1->cols * cn; + + for (int y = range.start; y < range.end; ++y) + { + const float * const weights1_row = weights1->ptr(y); + const float * const weights2_row = weights2->ptr(y); + const T * const src1_row = src1->ptr(y); + const T * const src2_row = src2->ptr(y); + T * const dst_row = dst->ptr(y); + + for (int x = 0; x < width; ++x) + { + int x1 = x / cn; + float w1 = weights1_row[x1], w2 = weights2_row[x1]; + float den = (w1 + w2 + 1e-5f); + float num = (src1_row[x] * w1 + src2_row[x] * w2); + + dst_row[x] = saturate_cast(num / den); + } + } + } + +private: + const BlendLinearInvoker & operator= (const BlendLinearInvoker &); + BlendLinearInvoker(const BlendLinearInvoker &); + + const Mat * src1, * src2, * weights1, * weights2; + Mat * dst; +}; + +static bool ocl_blendLinear( InputArray _src1, InputArray _src2, InputArray _weights1, InputArray _weights2, OutputArray _dst ) +{ + int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); + + char cvt[30]; + ocl::Kernel k("blendLinear", ocl::imgproc::blend_linear_oclsrc, + format("-D T=%s -D cn=%d -D convertToT=%s", ocl::typeToStr(depth), + cn, ocl::convertTypeStr(CV_32F, depth, 1, cvt))); + if (k.empty()) + return false; + + UMat src1 = _src1.getUMat(), src2 = _src2.getUMat(), weights1 = _weights1.getUMat(), + weights2 = _weights2.getUMat(), dst = _dst.getUMat(); + + k.args(ocl::KernelArg::ReadOnlyNoSize(src1), ocl::KernelArg::ReadOnlyNoSize(src2), + ocl::KernelArg::ReadOnlyNoSize(weights1), ocl::KernelArg::ReadOnlyNoSize(weights2), + ocl::KernelArg::WriteOnly(dst)); + + size_t globalsize[2] = { dst.cols, dst.rows }; + return k.run(2, globalsize, NULL, false); +} + +} + +void cv::blendLinear( InputArray _src1, InputArray _src2, InputArray _weights1, InputArray _weights2, OutputArray _dst ) +{ + int type = _src1.type(), depth = CV_MAT_DEPTH(type); + Size size = _src1.size(); + + CV_Assert(depth == CV_8U || depth == CV_32F); + CV_Assert(size == _src2.size() && size == _weights1.size() && size == _weights2.size()); + CV_Assert(type == _src2.type() && _weights1.type() == CV_32FC1 && _weights2.type() == CV_32FC1); + + _dst.create(size, type); + + if (ocl::useOpenCL() && _dst.isUMat() && ocl_blendLinear(_src1, _src2, _weights1, _weights2, _dst)) + return; + + Mat src1 = _src1.getMat(), src2 = _src2.getMat(), weights1 = _weights1.getMat(), + weights2 = _weights2.getMat(), dst = _dst.getMat(); + + if (depth == CV_8U) + { + BlendLinearInvoker invoker(src1, src2, weights1, weights2, dst); + parallel_for_(Range(0, src1.rows), invoker, dst.total()/(double)(1<<16)); + } + else if (depth == CV_32F) + { + BlendLinearInvoker invoker(src1, src2, weights1, weights2, dst); + parallel_for_(Range(0, src1.rows), invoker, dst.total()/(double)(1<<16)); + } +} diff --git a/modules/imgproc/src/opencl/blend_linear.cl b/modules/imgproc/src/opencl/blend_linear.cl new file mode 100644 index 0000000000..0644cae802 --- /dev/null +++ b/modules/imgproc/src/opencl/blend_linear.cl @@ -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) 2010-2012, MulticoreWare Inc., all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Liu Liujun, liujun@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 materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors as is and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including 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 DOUBLE_SUPPORT +#ifdef cl_amd_fp64 +#pragma OPENCL EXTENSION cl_amd_fp64:enable +#elif defined (cl_khr_fp64) +#pragma OPENCL EXTENSION cl_khr_fp64:enable +#endif +#endif + +#define noconvert + +__kernel void blendLinear(__global const uchar * src1ptr, int src1_step, int src1_offset, + __global const uchar * src2ptr, int src2_step, int src2_offset, + __global const uchar * weight1, int weight1_step, int weight1_offset, + __global const uchar * weight2, int weight2_step, int weight2_offset, + __global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols) +{ + int x = get_global_id(0); + int y = get_global_id(1); + + if (x < dst_cols && y < dst_rows) + { + int src1_index = mad24(y, src1_step, src1_offset + x * cn * (int)sizeof(T)); + int src2_index = mad24(y, src2_step, src2_offset + x * cn * (int)sizeof(T)); + int weight1_index = mad24(y, weight1_step, weight1_offset + x * (int)sizeof(float)); + int weight2_index = mad24(y, weight2_step, weight2_offset + x * (int)sizeof(float)); + int dst_index = mad24(y, dst_step, dst_offset + x * cn * (int)sizeof(T)); + + float w1 = *(__global const float *)(weight1 + weight1_index), + w2 = *(__global const float *)(weight2 + weight2_index); + float den = w1 + w2 + 1e-5f; + + __global const T * src1 = (__global const T *)(src1ptr + src1_index); + __global const T * src2 = (__global const T *)(src2ptr + src2_index); + __global T * dst = (__global T *)(dstptr + dst_index); + + #pragma unroll + for (int i = 0; i < cn; ++i) + { + float num = w1 * convert_float(src1[i]) + w2 * convert_float(src2[i]); + dst[i] = convertToT(num / den); + } + } +} diff --git a/modules/imgproc/test/ocl/test_blend.cpp b/modules/imgproc/test/ocl/test_blend.cpp new file mode 100644 index 0000000000..4cfe486d2f --- /dev/null +++ b/modules/imgproc/test/ocl/test_blend.cpp @@ -0,0 +1,129 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do 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-2012, Multicoreware, Inc., all rights reserved. +// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// @Authors +// Nathan, liujun@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 materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors as is and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including 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 "cvconfig.h" +#include "opencv2/ts/ocl_test.hpp" + +#ifdef HAVE_OPENCL + +namespace cvtest { +namespace ocl { + +PARAM_TEST_CASE(BlendLinear, MatDepth, Channels, bool) +{ + int depth, channels; + bool useRoi; + + TEST_DECLARE_INPUT_PARAMETER(src1) + TEST_DECLARE_INPUT_PARAMETER(src2) + TEST_DECLARE_INPUT_PARAMETER(weights2) + TEST_DECLARE_INPUT_PARAMETER(weights1) + TEST_DECLARE_OUTPUT_PARAMETER(dst) + + virtual void SetUp() + { + depth = GET_PARAM(0); + channels = GET_PARAM(1); + useRoi = GET_PARAM(2); + } + + void random_roi() + { + const int type = CV_MAKE_TYPE(depth, channels); + const double upValue = 256; + + Size roiSize = randomSize(1, 20); + Border src1Border = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(src1, src1_roi, roiSize, src1Border, type, -upValue, upValue); + + Border src2Border = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(src2, src2_roi, roiSize, src2Border, type, -upValue, upValue); + + Border weights1Border = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(weights1, weights1_roi, roiSize, weights1Border, CV_32FC1, -upValue, upValue); + + Border weights2Border = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(weights2, weights2_roi, roiSize, weights2Border, CV_32FC1, 1e-2, upValue); + + weights2_roi -= weights1_roi; + CV_Assert(checkNorm(weights2_roi, weights2(Rect(weights2Border.lef, weights2Border.top, + roiSize.width, roiSize.height))) < 1e-6); + + Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); + randomSubMat(dst, dst_roi, roiSize, dstBorder, type, 5, 16); + + UMAT_UPLOAD_INPUT_PARAMETER(src1) + UMAT_UPLOAD_INPUT_PARAMETER(src2) + UMAT_UPLOAD_INPUT_PARAMETER(weights1) + UMAT_UPLOAD_INPUT_PARAMETER(weights2) + UMAT_UPLOAD_OUTPUT_PARAMETER(dst) + } + + void Near(double eps = 0.0) + { + EXPECT_MAT_NEAR(dst, udst, eps); + EXPECT_MAT_NEAR(dst_roi, udst_roi, eps); + } +}; + +OCL_TEST_P(BlendLinear, Accuracy) +{ + for (int i = 0; i < test_loop_times; ++i) + { + random_roi(); + + OCL_OFF(cv::blendLinear(src1_roi, src2_roi, weights1_roi, weights2_roi, dst_roi)); + OCL_ON(cv::blendLinear(usrc1_roi, usrc2_roi, uweights1_roi, uweights2_roi, udst_roi)); + + Near(depth <= CV_32S ? 1.0 : 0.2); + } +} + +OCL_INSTANTIATE_TEST_CASE_P(ImgProc, BlendLinear, Combine(testing::Values(CV_8U, CV_32F), OCL_ALL_CHANNELS, Bool())); + +} } // namespace cvtest::ocl + +#endif From 5566d314682a766c3b9152a76b58053e05a1abf3 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 10 Dec 2013 16:27:21 +0400 Subject: [PATCH 92/97] more strict checks outside ROI --- modules/core/src/convert.cpp | 10 ++++---- modules/core/test/ocl/test_arithm.cpp | 12 ++++------ modules/core/test/ocl/test_split_merge.cpp | 3 +-- modules/imgproc/test/ocl/test_color.cpp | 3 +-- modules/imgproc/test/ocl/test_imgproc.cpp | 28 ++++++---------------- modules/imgproc/test/ocl/test_warp.cpp | 9 +++---- modules/ts/include/opencv2/ts/ocl_test.hpp | 22 ++++++++++++++++- 7 files changed, 43 insertions(+), 44 deletions(-) diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 1b1ceac2c4..05c1a6e402 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -1306,9 +1306,10 @@ namespace cv { static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst) { - int dcn = _dst.channels(), lcn = _lut.channels(), dtype = _dst.type(); + int dtype = _dst.type(), lcn = _lut.channels(), dcn = CV_MAT_CN(dtype), ddepth = CV_MAT_DEPTH(dtype); + bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; - if (_src.dims() > 2) + if (_src.dims() > 2 || (!doubleSupport && ddepth == CV_64F)) return false; UMat src = _src.getUMat(), lut = _lut.getUMat(); @@ -1316,8 +1317,9 @@ static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst) UMat dst = _dst.getUMat(); ocl::Kernel k("LUT", ocl::core::lut_oclsrc, - format("-D dcn=%d -D lcn=%d -D srcT=%s -D dstT=%s", dcn, lcn, - ocl::typeToStr(src.depth()), ocl::typeToStr(dst.depth()))); + format("-D dcn=%d -D lcn=%d -D srcT=%s -D dstT=%s%s", dcn, lcn, + ocl::typeToStr(src.depth()), ocl::typeToStr(ddepth), + doubleSupport ? " -D DOUBLE_SUPPORT" : "")); k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::ReadOnlyNoSize(lut), ocl::KernelArg::WriteOnly(dst)); diff --git a/modules/core/test/ocl/test_arithm.cpp b/modules/core/test/ocl/test_arithm.cpp index 045fbd7c49..e14fd67f55 100644 --- a/modules/core/test/ocl/test_arithm.cpp +++ b/modules/core/test/ocl/test_arithm.cpp @@ -92,8 +92,7 @@ PARAM_TEST_CASE(Lut, MatDepth, MatDepth, Channels, bool, bool) void Near(double threshold = 0.) { - EXPECT_MAT_NEAR(dst, udst, threshold); - EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold); + OCL_EXPECT_MATS_NEAR(dst, threshold) } }; @@ -165,14 +164,12 @@ PARAM_TEST_CASE(ArithmTestBase, MatDepth, Channels, bool) void Near(double threshold = 0.) { - EXPECT_MAT_NEAR(dst1, udst1, threshold); - EXPECT_MAT_NEAR(dst1_roi, udst1_roi, threshold); + OCL_EXPECT_MATS_NEAR(dst1, threshold) } void Near1(double threshold = 0.) { - EXPECT_MAT_NEAR(dst2, udst2, threshold); - EXPECT_MAT_NEAR(dst2_roi, udst2_roi, threshold); + OCL_EXPECT_MATS_NEAR(dst2, threshold) } }; @@ -532,8 +529,7 @@ OCL_TEST_P(Transpose, SquareInplace) OCL_OFF(cv::transpose(src1_roi, src1_roi)); OCL_ON(cv::transpose(usrc1_roi, usrc1_roi)); - EXPECT_MAT_NEAR(src1, usrc1, 0.0); - EXPECT_MAT_NEAR(src1_roi, usrc1_roi, 0.0); + OCL_EXPECT_MATS_NEAR(src1, 0) } } diff --git a/modules/core/test/ocl/test_split_merge.cpp b/modules/core/test/ocl/test_split_merge.cpp index 224963cd24..0fa0b1958a 100644 --- a/modules/core/test/ocl/test_split_merge.cpp +++ b/modules/core/test/ocl/test_split_merge.cpp @@ -113,8 +113,7 @@ PARAM_TEST_CASE(MergeTestBase, MatDepth, Channels, bool) void Near(double threshold = 0.) { - EXPECT_MAT_NEAR(dst, udst, threshold); - EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold); + OCL_EXPECT_MATS_NEAR(dst, threshold); } }; diff --git a/modules/imgproc/test/ocl/test_color.cpp b/modules/imgproc/test/ocl/test_color.cpp index 5bcfa1bac9..4c0f8b3113 100644 --- a/modules/imgproc/test/ocl/test_color.cpp +++ b/modules/imgproc/test/ocl/test_color.cpp @@ -86,8 +86,7 @@ PARAM_TEST_CASE(CvtColor, MatDepth, bool) void Near(double threshold) { - EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold); - EXPECT_MAT_NEAR(dst, udst, threshold); + OCL_EXPECT_MATS_NEAR(dst, threshold) } void performTest(int channelsIn, int channelsOut, int code, double threshold = 1e-3) diff --git a/modules/imgproc/test/ocl/test_imgproc.cpp b/modules/imgproc/test/ocl/test_imgproc.cpp index 9089b55927..d6799ce450 100644 --- a/modules/imgproc/test/ocl/test_imgproc.cpp +++ b/modules/imgproc/test/ocl/test_imgproc.cpp @@ -97,15 +97,9 @@ PARAM_TEST_CASE(ImgprocTestBase, MatType, void Near(double threshold = 0.0, bool relative = false) { if (relative) - { - EXPECT_MAT_NEAR_RELATIVE(dst, udst, threshold); - EXPECT_MAT_NEAR_RELATIVE(dst_roi, udst_roi, threshold); - } + OCL_EXPECT_MATS_NEAR_RELATIVE(dst, threshold) else - { - EXPECT_MAT_NEAR(dst, udst, threshold); - EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold); - } + OCL_EXPECT_MATS_NEAR(dst, threshold) } }; @@ -158,10 +152,9 @@ PARAM_TEST_CASE(CopyMakeBorder, MatDepth, // depth UMAT_UPLOAD_OUTPUT_PARAMETER(dst) } - void Near(double threshold = 0.0) + void Near() { - EXPECT_MAT_NEAR(dst, udst, threshold); - EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold); + OCL_EXPECT_MATS_NEAR(dst, 0) } }; @@ -305,15 +298,9 @@ struct Integral : void Near2(double threshold = 0.0, bool relative = false) { if (relative) - { - EXPECT_MAT_NEAR_RELATIVE(dst2, udst2, threshold); - EXPECT_MAT_NEAR_RELATIVE(dst2_roi, udst2_roi, threshold); - } + OCL_EXPECT_MATS_NEAR_RELATIVE(dst2, threshold) else - { - EXPECT_MAT_NEAR(dst2, udst2, threshold); - EXPECT_MAT_NEAR(dst2_roi, udst2_roi, threshold); - } + OCL_EXPECT_MATS_NEAR(dst2, threshold) } }; @@ -412,8 +399,7 @@ PARAM_TEST_CASE(CLAHETest, Size, double, bool) void Near(double threshold = 0.0) { - EXPECT_MAT_NEAR(dst, udst, threshold); - EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold); + OCL_EXPECT_MATS_NEAR(dst, threshold) } }; diff --git a/modules/imgproc/test/ocl/test_warp.cpp b/modules/imgproc/test/ocl/test_warp.cpp index c05c33590a..d5c75f0dad 100644 --- a/modules/imgproc/test/ocl/test_warp.cpp +++ b/modules/imgproc/test/ocl/test_warp.cpp @@ -104,8 +104,7 @@ PARAM_TEST_CASE(WarpTestBase, MatType, Interpolation, bool, bool) void Near(double threshold = 0.0) { - EXPECT_MAT_NEAR(dst, udst, threshold); - EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold); + OCL_EXPECT_MATS_NEAR(dst, threshold) } }; @@ -203,8 +202,7 @@ PARAM_TEST_CASE(Resize, MatType, double, double, Interpolation, bool) void Near(double threshold = 0.0) { - EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold); - EXPECT_MAT_NEAR(dst, udst, threshold); + OCL_EXPECT_MATS_NEAR(dst, threshold) } }; @@ -280,8 +278,7 @@ PARAM_TEST_CASE(Remap, MatDepth, Channels, std::pair, BorderTy void Near(double threshold = 0.0) { - EXPECT_MAT_NEAR(dst, udst, threshold); - EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold); + OCL_EXPECT_MATS_NEAR(dst, threshold) } }; diff --git a/modules/ts/include/opencv2/ts/ocl_test.hpp b/modules/ts/include/opencv2/ts/ocl_test.hpp index 1b66799ed0..b14626553e 100644 --- a/modules/ts/include/opencv2/ts/ocl_test.hpp +++ b/modules/ts/include/opencv2/ts/ocl_test.hpp @@ -110,6 +110,26 @@ extern int test_loop_times; << cv::format("Size: %d x %d", mat1.size().width, mat1.size().height) << std::endl; \ } +#define OCL_EXPECT_MATS_NEAR(name, eps) \ +{ \ + EXPECT_MAT_NEAR(name ## _roi, u ## name ## _roi, eps); \ + int nextValue = rng.next(); \ + RNG dataRng1(nextValue), dataRng2(nextValue); \ + dataRng1.fill(name ## _roi, RNG::UNIFORM, Scalar::all(-MAX_VALUE), Scalar::all(MAX_VALUE)); \ + dataRng2.fill(u ## name ## _roi, RNG::UNIFORM, Scalar::all(-MAX_VALUE), Scalar::all(MAX_VALUE)); \ + EXPECT_MAT_NEAR(name, u ## name, 0/*FLT_EPSILON*/); \ +} + +#define OCL_EXPECT_MATS_NEAR_RELATIVE(name, eps) \ +{ \ + EXPECT_MAT_NEAR_RELATIVE(name ## _roi, u ## name ## _roi, eps); \ + int nextValue = rng.next(); \ + RNG dataRng1(nextValue), dataRng2(nextValue); \ + dataRng1.fill(name ## _roi, RNG::UNIFORM, Scalar::all(-MAX_VALUE), Scalar::all(MAX_VALUE)); \ + dataRng2.fill(u ## name ## _roi, RNG::UNIFORM, Scalar::all(-MAX_VALUE), Scalar::all(MAX_VALUE)); \ + EXPECT_MAT_NEAR_RELATIVE(name, u ## name, 0/*FLT_EPSILON*/); \ +} + #define EXPECT_MAT_SIMILAR(mat1, mat2, eps) \ { \ ASSERT_EQ(mat1.type(), mat2.type()); \ @@ -302,7 +322,7 @@ IMPLEMENT_PARAM_CLASS(Channels, int) #define OCL_OFF(fn) cv::ocl::setUseOpenCL(false); fn #define OCL_ON(fn) cv::ocl::setUseOpenCL(true); fn -#define OCL_ALL_DEPTHS Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F) +#define OCL_ALL_DEPTHS Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F) #define OCL_ALL_CHANNELS Values(1, 2, 3, 4) CV_ENUM(Interpolation, INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, INTER_AREA) From 8fa8b36b42d633f0c659d4a03811241d5ef81c94 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Tue, 10 Dec 2013 20:14:37 +0400 Subject: [PATCH 93/97] added cv::Laplacian, cv::Sobel, cv::Scharr, cv::GaussianBlur to T-API --- modules/imgproc/src/deriv.cpp | 47 ++++---- modules/imgproc/src/smooth.cpp | 44 ++++--- modules/imgproc/test/ocl/test_filters.cpp | 128 +++++++++++++++++++-- modules/ts/include/opencv2/ts/ocl_test.hpp | 2 +- 4 files changed, 176 insertions(+), 45 deletions(-) diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index eca0db3fde..bc11b24635 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -413,15 +413,15 @@ static bool IPPDeriv(const Mat& src, Mat& dst, int ddepth, int dx, int dy, int k void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType ) { - Mat src = _src.getMat(); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if (ddepth < 0) - ddepth = src.depth(); - _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); - Mat dst = _dst.getMat(); + ddepth = sdepth; + _dst.create( _src.size(), CV_MAKETYPE(ddepth, cn) ); #ifdef HAVE_TEGRA_OPTIMIZATION if (scale == 1.0 && delta == 0) { + Mat src = _src.getMat(), dst = _dst.getMat(); if (ksize == 3 && tegra::sobel3x3(src, dst, dx, dy, borderType)) return; if (ksize == -1 && tegra::scharr(src, dst, dx, dy, borderType)) @@ -430,13 +430,14 @@ void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, #endif #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - if(dx < 3 && dy < 3 && src.channels() == 1 && borderType == 1) + if(dx < 3 && dy < 3 && cn == 1 && borderType == BORDER_REPLICATE) { + Mat src = _src.getMat(), dst = _dst.getMat(); if(IPPDeriv(src, dst, ddepth, dx, dy, ksize,scale)) return; } #endif - int ktype = std::max(CV_32F, std::max(ddepth, src.depth())); + int ktype = std::max(CV_32F, std::max(ddepth, sdepth)); Mat kx, ky; getDerivKernels( kx, ky, dx, dy, ksize, false, ktype ); @@ -449,33 +450,36 @@ void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, else ky *= scale; } - sepFilter2D( src, dst, ddepth, kx, ky, Point(-1,-1), delta, borderType ); + sepFilter2D( _src, _dst, ddepth, kx, ky, Point(-1, -1), delta, borderType ); } void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, double scale, double delta, int borderType ) { - Mat src = _src.getMat(); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if (ddepth < 0) - ddepth = src.depth(); - _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); - Mat dst = _dst.getMat(); + ddepth = sdepth; + _dst.create( _src.size(), CV_MAKETYPE(ddepth, cn) ); #ifdef HAVE_TEGRA_OPTIMIZATION if (scale == 1.0 && delta == 0) + { + Mat src = _src.getMat(), dst = _dst.getMat(); if (tegra::scharr(src, dst, dx, dy, borderType)) return; + } #endif #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) if(dx < 2 && dy < 2 && src.channels() == 1 && borderType == 1) { + Mat src = _src.getMat(), dst = _dst.getMat(); if(IPPDerivScharr(src, dst, ddepth, dx, dy, scale)) return; } #endif - int ktype = std::max(CV_32F, std::max(ddepth, src.depth())); + int ktype = std::max(CV_32F, std::max(ddepth, sdepth)); Mat kx, ky; getScharrKernels( kx, ky, dx, dy, false, ktype ); @@ -488,22 +492,22 @@ void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, else ky *= scale; } - sepFilter2D( src, dst, ddepth, kx, ky, Point(-1,-1), delta, borderType ); + sepFilter2D( _src, _dst, ddepth, kx, ky, Point(-1, -1), delta, borderType ); } void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize, double scale, double delta, int borderType ) { - Mat src = _src.getMat(); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if (ddepth < 0) - ddepth = src.depth(); - _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); - Mat dst = _dst.getMat(); + ddepth = sdepth; + _dst.create( _src.size(), CV_MAKETYPE(ddepth, cn) ); #ifdef HAVE_TEGRA_OPTIMIZATION if (scale == 1.0 && delta == 0) { + Mat src = _src.getMat(), dst = _dst.getMat(); if (ksize == 1 && tegra::laplace1(src, dst, borderType)) return; if (ksize == 3 && tegra::laplace3(src, dst, borderType)) @@ -516,15 +520,18 @@ void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize, if( ksize == 1 || ksize == 3 ) { float K[2][9] = - {{0, 1, 0, 1, -4, 1, 0, 1, 0}, - {2, 0, 2, 0, -8, 0, 2, 0, 2}}; + { + { 0, 1, 0, 1, -4, 1, 0, 1, 0 }, + { 2, 0, 2, 0, -8, 0, 2, 0, 2 } + }; Mat kernel(3, 3, CV_32F, K[ksize == 3]); if( scale != 1 ) kernel *= scale; - filter2D( src, dst, ddepth, kernel, Point(-1,-1), delta, borderType ); + filter2D( _src, _dst, ddepth, kernel, Point(-1, -1), delta, borderType ); } else { + Mat src = _src.getMat(), dst = _dst.getMat(); const size_t STRIPE_SIZE = 1 << 14; int depth = src.depth(); diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 7ef850863f..9d280c9878 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -798,10 +798,10 @@ cv::Mat cv::getGaussianKernel( int n, double sigma, int ktype ) return kernel; } +namespace cv { -cv::Ptr cv::createGaussianFilter( int type, Size ksize, - double sigma1, double sigma2, - int borderType ) +static void createGaussianKernels( Mat & kx, Mat & ky, int type, Size ksize, + double sigma1, double sigma2 ) { int depth = CV_MAT_DEPTH(type); if( sigma2 <= 0 ) @@ -819,12 +819,21 @@ cv::Ptr cv::createGaussianFilter( int type, Size ksize, sigma1 = std::max( sigma1, 0. ); sigma2 = std::max( sigma2, 0. ); - Mat kx = getGaussianKernel( ksize.width, sigma1, std::max(depth, CV_32F) ); - Mat ky; + kx = getGaussianKernel( ksize.width, sigma1, std::max(depth, CV_32F) ); if( ksize.height == ksize.width && std::abs(sigma1 - sigma2) < DBL_EPSILON ) ky = kx; else ky = getGaussianKernel( ksize.height, sigma2, std::max(depth, CV_32F) ); +} + +} + +cv::Ptr cv::createGaussianFilter( int type, Size ksize, + double sigma1, double sigma2, + int borderType ) +{ + Mat kx, ky; + createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2); return createSeparableLinearFilter( type, type, kx, ky, Point(-1,-1), 0, borderType ); } @@ -834,33 +843,34 @@ void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, double sigma1, double sigma2, int borderType ) { - Mat src = _src.getMat(); - _dst.create( src.size(), src.type() ); - Mat dst = _dst.getMat(); + int type = _src.type(); + Size size = _src.size(); + _dst.create( size, type ); if( borderType != BORDER_CONSTANT ) { - if( src.rows == 1 ) + if( size.height == 1 ) ksize.height = 1; - if( src.cols == 1 ) + if( size.width == 1 ) ksize.width = 1; } if( ksize.width == 1 && ksize.height == 1 ) { - src.copyTo(dst); + _src.copyTo(_dst); return; } #ifdef HAVE_TEGRA_OPTIMIZATION - if(sigma1 == 0 && sigma2 == 0 && tegra::gaussian(src, dst, ksize, borderType)) + if(sigma1 == 0 && sigma2 == 0 && tegra::gaussian(_src.getMat(), _dst.getMat(), ksize, borderType)) return; #endif #if defined HAVE_IPP && (IPP_VERSION_MAJOR >= 7) - if(src.type() == CV_32FC1 && sigma1 == sigma2 && ksize.width == ksize.height && sigma1 != 0.0 ) + if( type == CV_32FC1 && sigma1 == sigma2 && ksize.width == ksize.height && sigma1 != 0.0 ) { - IppiSize roi = {src.cols, src.rows}; + Mat src = _src.getMat(), dst = _dst.getMat(); + IppiSize roi = { src.cols, src.rows }; int bufSize = 0; ippiFilterGaussGetBufferSize_32f_C1R(roi, ksize.width, &bufSize); AutoBuffer buf(bufSize+128); @@ -873,11 +883,11 @@ void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, } #endif - Ptr f = createGaussianFilter( src.type(), ksize, sigma1, sigma2, borderType ); - f->apply( src, dst ); + Mat kx, ky; + createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2); + sepFilter2D(_src, _dst, CV_MAT_DEPTH(type), kx, ky, Point(-1,-1), 0, borderType ); } - /****************************************************************************************\ Median Filter \****************************************************************************************/ diff --git a/modules/imgproc/test/ocl/test_filters.cpp b/modules/imgproc/test/ocl/test_filters.cpp index 58d23e8358..5953d80701 100644 --- a/modules/imgproc/test/ocl/test_filters.cpp +++ b/modules/imgproc/test/ocl/test_filters.cpp @@ -60,7 +60,7 @@ namespace ocl { PARAM_TEST_CASE(FilterTestBase, MatType, int, // kernel size Size, // dx, dy - int, // border type + BorderType, // border type double, // optional parameter bool) // roi or not { @@ -145,32 +145,146 @@ OCL_TEST_P(Bilateral, Mat) } } +///////////////////////////////////////////////////////////////////////////////////////////////// +// Laplacian + +typedef FilterTestBase LaplacianTest; + +OCL_TEST_P(LaplacianTest, Accuracy) +{ + double scale = param; + + for (int j = 0; j < test_loop_times; j++) + { + random_roi(); + + OCL_OFF(cv::Laplacian(src_roi, dst_roi, -1, ksize, scale, 0, borderType)); + OCL_ON(cv::Laplacian(usrc_roi, udst_roi, -1, ksize, scale, 0, borderType)); + + Near(); + } +} + + +///////////////////////////////////////////////////////////////////////////////////////////////// +// Sobel + +typedef FilterTestBase SobelTest; + +OCL_TEST_P(SobelTest, Mat) +{ + int dx = size.width, dy = size.height; + double scale = param; + + for (int j = 0; j < test_loop_times; j++) + { + random_roi(); + + OCL_OFF(cv::Sobel(src_roi, dst_roi, -1, dx, dy, ksize, scale, /* delta */0, borderType)); + OCL_ON(cv::Sobel(usrc_roi, udst_roi, -1, dx, dy, ksize, scale, /* delta */0, borderType)); + + Near(); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////// +// Scharr + +typedef FilterTestBase ScharrTest; + +OCL_TEST_P(ScharrTest, Mat) +{ + int dx = size.width, dy = size.height; + double scale = param; + + for (int j = 0; j < test_loop_times; j++) + { + random_roi(); + + OCL_OFF(cv::Scharr(src_roi, dst_roi, -1, dx, dy, scale, /* delta */ 0, borderType)); + OCL_ON(cv::Scharr(usrc_roi, udst_roi, -1, dx, dy, scale, /* delta */ 0, borderType)); + + Near(); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////// +// GaussianBlur + +typedef FilterTestBase GaussianBlurTest; + +OCL_TEST_P(GaussianBlurTest, Mat) +{ + for (int j = 0; j < test_loop_times; j++) + { + random_roi(); + + double sigma1 = rng.uniform(0.1, 1.0); + double sigma2 = rng.uniform(0.1, 1.0); + + OCL_OFF(cv::GaussianBlur(src_roi, dst_roi, Size(ksize, ksize), sigma1, sigma2, borderType)); + OCL_ON(cv::GaussianBlur(usrc_roi, udst_roi, Size(ksize, ksize), sigma1, sigma2, borderType)); + + Near(CV_MAT_DEPTH(type) == CV_8U ? 3 : 5e-5, false); + } +} + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// #define FILTER_BORDER_SET_NO_ISOLATED \ - Values((int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, (int)BORDER_WRAP, (int)BORDER_REFLECT_101/*, \ + Values((BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE, (BorderType)BORDER_REFLECT, (BorderType)BORDER_WRAP, (BorderType)BORDER_REFLECT_101/*, \ (int)BORDER_CONSTANT|BORDER_ISOLATED, (int)BORDER_REPLICATE|BORDER_ISOLATED, \ (int)BORDER_REFLECT|BORDER_ISOLATED, (int)BORDER_WRAP|BORDER_ISOLATED, \ (int)BORDER_REFLECT_101|BORDER_ISOLATED*/) // WRAP and ISOLATED are not supported by cv:: version #define FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED \ - Values((int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, /*(int)BORDER_WRAP,*/ (int)BORDER_REFLECT_101/*, \ + Values((BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE, (BorderType)BORDER_REFLECT, /*(int)BORDER_WRAP,*/ (BorderType)BORDER_REFLECT_101/*, \ (int)BORDER_CONSTANT|BORDER_ISOLATED, (int)BORDER_REPLICATE|BORDER_ISOLATED, \ (int)BORDER_REFLECT|BORDER_ISOLATED, (int)BORDER_WRAP|BORDER_ISOLATED, \ (int)BORDER_REFLECT_101|BORDER_ISOLATED*/) // WRAP and ISOLATED are not supported by cv:: version -#define FILTER_DATATYPES Values(CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4, \ - CV_32FC1, CV_32FC3, CV_32FC4, \ - CV_64FC1, CV_64FC3, CV_64FC4) +#define FILTER_TYPES Values(CV_8UC1, CV_8UC2, CV_8UC4, CV_32FC1, CV_32FC4, CV_64FC1, CV_64FC4) OCL_INSTANTIATE_TEST_CASE_P(Filter, Bilateral, Combine( Values((MatType)CV_8UC1), - Values(5, 9), + Values(5, 9), // kernel size Values(Size(0, 0)), // not used FILTER_BORDER_SET_NO_ISOLATED, Values(0.0), // not used Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Filter, LaplacianTest, Combine( + FILTER_TYPES, + Values(1, 3), // kernel size + Values(Size(0, 0)), // not used + FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, + Values(1.0, 0.2, 3.0), // kernel scale + Bool())); + +OCL_INSTANTIATE_TEST_CASE_P(Filter, SobelTest, Combine( + FILTER_TYPES, + Values(3, 5), // kernel size + Values(Size(1, 0), Size(1, 1), Size(2, 0), Size(2, 1)), // dx, dy + FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, + Values(0.0), // not used + Bool())); + +OCL_INSTANTIATE_TEST_CASE_P(Filter, ScharrTest, Combine( + FILTER_TYPES, + Values(0), // not used + Values(Size(0, 1), Size(1, 0)), // dx, dy + FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, + Values(1.0, 0.2), // kernel scale + Bool())); + +OCL_INSTANTIATE_TEST_CASE_P(Filter, GaussianBlurTest, Combine( + FILTER_TYPES, + Values(3, 5), // kernel size + Values(Size(0, 0)), // not used + FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, + Values(0.0), // not used + Bool())); + } } // namespace cvtest::ocl #endif // HAVE_OPENCL diff --git a/modules/ts/include/opencv2/ts/ocl_test.hpp b/modules/ts/include/opencv2/ts/ocl_test.hpp index 1b66799ed0..a9604612c1 100644 --- a/modules/ts/include/opencv2/ts/ocl_test.hpp +++ b/modules/ts/include/opencv2/ts/ocl_test.hpp @@ -307,7 +307,7 @@ IMPLEMENT_PARAM_CLASS(Channels, int) CV_ENUM(Interpolation, INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, INTER_AREA) CV_ENUM(ThreshOp, THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV) -CV_ENUM(BorderType, BORDER_REPLICATE, BORDER_REFLECT, BORDER_WRAP, BORDER_REFLECT_101) +CV_ENUM(BorderType, BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT, BORDER_WRAP, BORDER_REFLECT_101) #define OCL_INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ INSTANTIATE_TEST_CASE_P(OCL_ ## prefix, test_case_name, generator) From bdbd3eb2bfe8f1b1da708cb4a349f7e96aa04626 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Wed, 11 Dec 2013 00:31:34 +0400 Subject: [PATCH 94/97] ocl: process termination hung workaround --- modules/core/src/ocl.cpp | 11 ++++++++--- modules/core/src/precomp.hpp | 3 +++ modules/core/src/system.cpp | 9 +++++++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 0cff7b5fdd..96a006f1c5 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -1932,10 +1932,15 @@ struct Queue::Impl ~Impl() { - if(handle) +#ifdef _WIN32 + if (!cv::__termination) +#endif { - clFinish(handle); - clReleaseCommandQueue(handle); + if(handle) + { + clFinish(handle); + clReleaseCommandQueue(handle); + } } } diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index 7465685fd6..87104aff80 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -249,6 +249,9 @@ namespace ocl MatAllocator* getOpenCLAllocator(); } +extern bool __termination; // skip some cleanups, because process is terminating + // (for example, if ExitProcess() was already called) + } #endif /*_CXCORE_INTERNAL_H_*/ diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index eee06e2905..27865971b7 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -734,18 +734,23 @@ cvErrorFromIppStatus( int status ) } } +namespace cv { +bool __termination = false; +} #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, LPVOID ); -BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID ) +BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID lpReserved ) { if( fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH ) { + if (lpReserved != NULL) // called after ExitProcess() call + cv::__termination = true; cv::deleteThreadAllocData(); cv::deleteThreadData(); } From e7227d3e4b4b0e816b17a57b7ade9e39030c18dc Mon Sep 17 00:00:00 2001 From: Vladimir Bystricky Date: Wed, 11 Dec 2013 14:26:33 +0400 Subject: [PATCH 95/97] Fix problems with border extrapolation in kernel. Add Isolated/Nonisolated borders. --- modules/imgproc/src/filter.cpp | 27 +++++++++++++++--- modules/imgproc/src/opencl/filter2D.cl | 32 ++++++++++------------ modules/imgproc/test/ocl/test_filter2d.cpp | 27 +++++++++--------- 3 files changed, 51 insertions(+), 35 deletions(-) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 832b0d0381..d548168491 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -3210,6 +3210,13 @@ static bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth, size_t localsize[2] = {0, 1}; ocl::Kernel kernel; + UMat src; Size wholeSize; + if (!isIsolatedBorder) + { + src = _src.getUMat(); + Point ofs; + src.locateROI(wholeSize, ofs); + } size_t maxWorkItemSizes[32]; device.maxWorkItemSizes(maxWorkItemSizes); size_t tryWorkItems = maxWorkItemSizes[0]; @@ -3233,8 +3240,8 @@ static bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth, int requiredLeft = (int)BLOCK_SIZE; // not this: anchor.x; int requiredBottom = ksize.height - 1 - anchor.y; int requiredRight = (int)BLOCK_SIZE; // not this: ksize.width - 1 - anchor.x; - int h = sz.height; - int w = sz.width; + int h = isIsolatedBorder ? sz.height : wholeSize.height; + int w = isIsolatedBorder ? sz.width : wholeSize.width; bool extra_extrapolation = h < requiredTop || h < requiredBottom || w < requiredLeft || w < requiredRight; if ((w < ksize.width) || (h < ksize.height)) @@ -3268,10 +3275,22 @@ static bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth, _dst.create(sz, CV_MAKETYPE(ddepth, cn)); UMat dst = _dst.getUMat(); - UMat src = _src.getUMat(); + if (src.empty()) + src = _src.getUMat(); int idxArg = 0; - idxArg = kernel.set(idxArg, ocl::KernelArg::ReadOnlyNoSize(src)); + idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(src)); + idxArg = kernel.set(idxArg, (int)src.step); + + int srcOffsetX = (int)((src.offset % src.step) / src.elemSize()); + int srcOffsetY = (int)(src.offset / src.step); + int srcEndX = (isIsolatedBorder ? (srcOffsetX + sz.width) : wholeSize.width); + int srcEndY = (isIsolatedBorder ? (srcOffsetY + sz.height) : wholeSize.height); + idxArg = kernel.set(idxArg, srcOffsetX); + idxArg = kernel.set(idxArg, srcOffsetY); + idxArg = kernel.set(idxArg, srcEndX); + idxArg = kernel.set(idxArg, srcEndY); + idxArg = kernel.set(idxArg, ocl::KernelArg::WriteOnly(dst)); float borderValue[4] = {0, 0, 0, 0}; double borderValueDouble[4] = {0, 0, 0, 0}; diff --git a/modules/imgproc/src/opencl/filter2D.cl b/modules/imgproc/src/opencl/filter2D.cl index 1225be93fc..d360714971 100644 --- a/modules/imgproc/src/opencl/filter2D.cl +++ b/modules/imgproc/src/opencl/filter2D.cl @@ -102,7 +102,7 @@ do \ { \ if (x < minX) \ - x = -(x - minX) - 1 + delta; \ + x = minX - (x - minX) - 1 + delta; \ else \ x = maxX - 1 - (x - maxX) - delta; \ } \ @@ -114,7 +114,7 @@ do \ { \ if (y < minY) \ - y = -(y - minY) - 1 + delta; \ + y = minY - (y - minY) - 1 + delta; \ else \ y = maxY - 1 - (y - maxY) - delta; \ } \ @@ -222,7 +222,7 @@ struct RectCoords #endif -inline INTERMEDIATE_TYPE readSrcPixel(int2 pos, __global const uchar* srcptr, int srcstep, int srcoffset, const struct RectCoords srcCoords +inline INTERMEDIATE_TYPE readSrcPixel(int2 pos, __global const uchar* srcptr, int srcstep, const struct RectCoords srcCoords #ifdef BORDER_CONSTANT , SCALAR_TYPE borderValue #endif @@ -235,7 +235,7 @@ inline INTERMEDIATE_TYPE readSrcPixel(int2 pos, __global const uchar* srcptr, in #endif { //__global TYPE* ptr = (__global TYPE*)((__global char*)src + pos.x * sizeof(TYPE) + pos.y * srcStepBytes); - __global TYPE* ptr = (__global TYPE*)(srcptr + pos.y * srcstep + srcoffset + pos.x * sizeof(TYPE)); + __global TYPE* ptr = (__global TYPE*)(srcptr + pos.y * srcstep + pos.x * sizeof(TYPE)); return CONVERT_TO_FPTYPE(*ptr); } else @@ -262,7 +262,7 @@ inline INTERMEDIATE_TYPE readSrcPixel(int2 pos, __global const uchar* srcptr, in if(pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2) { //__global TYPE* ptr = (__global TYPE*)((__global char*)src + pos.x * sizeof(TYPE) + pos.y * srcStepBytes); - __global TYPE* ptr = (__global TYPE*)(srcptr + pos.y * srcstep + srcoffset + pos.x * sizeof(TYPE)); + __global TYPE* ptr = (__global TYPE*)(srcptr + pos.y * srcstep + pos.x * sizeof(TYPE)); return CONVERT_TO_FPTYPE(*ptr); } else @@ -279,8 +279,8 @@ inline INTERMEDIATE_TYPE readSrcPixel(int2 pos, __global const uchar* srcptr, in __kernel __attribute__((reqd_work_group_size(LOCAL_SIZE, 1, 1))) -void filter2D(__global const uchar* srcptr, int srcstep, int srcoffset, - __global uchar* dstptr, int dststep, int dstoffset, +void filter2D(__global const uchar* srcptr, int srcstep, int srcOffsetX, int srcOffsetY, int srcEndX, int srcEndY, + __global uchar* dstptr, int dststep, int dstoffset, int rows, int cols, #ifdef BORDER_CONSTANT SCALAR_TYPE borderValue, @@ -288,8 +288,7 @@ void filter2D(__global const uchar* srcptr, int srcstep, int srcoffset, __constant FPTYPE* kernelData // transposed: [KERNEL_SIZE_X][KERNEL_SIZE_Y2_ALIGNED] ) { - const struct RectCoords srcCoords = {0, 0, cols, rows}; // for non-isolated border: offsetX, offsetY, wholeX, wholeY - const struct RectCoords dstCoords = {0, 0, cols, rows}; + const struct RectCoords srcCoords = {srcOffsetX, srcOffsetY, srcEndX, srcEndY}; // for non-isolated border: offsetX, offsetY, wholeX, wholeY const int local_id = get_local_id(0); const int x = local_id + (LOCAL_SIZE - (KERNEL_SIZE_X - 1)) * get_group_id(0) - ANCHOR_X; @@ -300,23 +299,23 @@ void filter2D(__global const uchar* srcptr, int srcstep, int srcoffset, int2 srcPos = (int2)(srcCoords.x1 + x, srcCoords.y1 + y - ANCHOR_Y); - int2 pos = (int2)(dstCoords.x1 + x, dstCoords.y1 + y); + int2 pos = (int2)(x, y); __global TYPE* dstPtr = (__global TYPE*)((__global char*)dstptr + pos.y * dststep + dstoffset + pos.x * sizeof(TYPE)); // Pointer can be out of bounds! - bool writeResult = (local_id >= ANCHOR_X && local_id < LOCAL_SIZE - (KERNEL_SIZE_X - 1 - ANCHOR_X) && - pos.x >= dstCoords.x1 && pos.x < dstCoords.x2); + bool writeResult = ((local_id >= ANCHOR_X) && (local_id < LOCAL_SIZE - (KERNEL_SIZE_X - 1 - ANCHOR_X)) && + (pos.x >= 0) && (pos.x < cols)); #if BLOCK_SIZE_Y > 1 bool readAllpixels = true; int sy_index = 0; // current index in data[] array - dstCoords.y2 = min(dstCoords.y2, pos.y + BLOCK_SIZE_Y); + dstRowsMax = min(rows, pos.y + BLOCK_SIZE_Y); for (; - pos.y < dstCoords.y2; + pos.y < dstRowsMax; pos.y++, dstPtr = (__global TYPE*)((__global char*)dstptr + dststep)) #endif { - ASSERT(pos.y < dstCoords.y2); + ASSERT(pos.y < dstRowsMax); for ( #if BLOCK_SIZE_Y > 1 @@ -326,7 +325,7 @@ void filter2D(__global const uchar* srcptr, int srcstep, int srcoffset, #endif sy++, srcPos.y++) { - data[sy + sy_index] = readSrcPixel(srcPos, srcptr, srcstep, srcoffset, srcCoords + data[sy + sy_index] = readSrcPixel(srcPos, srcptr, srcstep, srcCoords #ifdef BORDER_CONSTANT , borderValue #endif @@ -361,7 +360,6 @@ void filter2D(__global const uchar* srcptr, int srcstep, int srcoffset, if (writeResult) { - ASSERT(pos.y >= dstCoords.y1 && pos.y < dstCoords.y2); *dstPtr = CONVERT_TO_TYPE(total_sum); } diff --git a/modules/imgproc/test/ocl/test_filter2d.cpp b/modules/imgproc/test/ocl/test_filter2d.cpp index ca1450952c..484080df44 100644 --- a/modules/imgproc/test/ocl/test_filter2d.cpp +++ b/modules/imgproc/test/ocl/test_filter2d.cpp @@ -49,17 +49,11 @@ namespace cvtest { namespace ocl { -enum -{ - noType = -1, -}; - - ///////////////////////////////////////////////////////////////////////////////////////////////// // Filter2D -PARAM_TEST_CASE(Filter2D, MatDepth, Channels, BorderType, bool) +PARAM_TEST_CASE(Filter2D, MatDepth, Channels, BorderType, bool, bool) { - static const int kernelMinSize = 1; + static const int kernelMinSize = 2; static const int kernelMaxSize = 10; int type; @@ -75,8 +69,8 @@ PARAM_TEST_CASE(Filter2D, MatDepth, Channels, BorderType, bool) virtual void SetUp() { type = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1)); - borderType = GET_PARAM(2); - useRoi = GET_PARAM(3); + borderType = GET_PARAM(2) | (GET_PARAM(3) ? BORDER_ISOLATED : 0); + useRoi = GET_PARAM(4); } void random_roi() @@ -84,16 +78,19 @@ PARAM_TEST_CASE(Filter2D, MatDepth, Channels, BorderType, bool) dsize = randomSize(1, MAX_VALUE); Size ksize = randomSize(kernelMinSize, kernelMaxSize); - kernel = randomMat(ksize, CV_MAKE_TYPE(((CV_64F == CV_MAT_DEPTH(type)) ? CV_64F : CV_32F), 1), -MAX_VALUE, MAX_VALUE); + Mat temp = randomMat(ksize, CV_MAKE_TYPE(((CV_64F == CV_MAT_DEPTH(type)) ? CV_64F : CV_32F), 1), -MAX_VALUE, MAX_VALUE); + cv::normalize(temp, kernel, 1.0, 0.0, NORM_L1); - Size roiSize = randomSize(1, MAX_VALUE); + //Size roiSize = randomSize(ksize.width, MAX_VALUE, ksize.height, MAX_VALUE); + Size roiSize(1024, 1024); Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE); Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); randomSubMat(dst, dst_roi, dsize, dstBorder, type, -MAX_VALUE, MAX_VALUE); - anchor.x = anchor.y = -1; + anchor.x = randomInt(-1, ksize.width); + anchor.y = randomInt(-1, ksize.height); UMAT_UPLOAD_INPUT_PARAMETER(src) UMAT_UPLOAD_OUTPUT_PARAMETER(dst) @@ -128,7 +125,9 @@ OCL_INSTANTIATE_TEST_CASE_P(ImageProc, Filter2D, (BorderType)BORDER_REPLICATE, (BorderType)BORDER_REFLECT, (BorderType)BORDER_REFLECT_101), - Bool()) + Bool(), // BORDER_ISOLATED + Bool() // ROI + ) ); From f76bf8b425dd5af8a94517a35868f7f3514e34f3 Mon Sep 17 00:00:00 2001 From: Vladimir Bystricky Date: Wed, 11 Dec 2013 14:33:22 +0400 Subject: [PATCH 96/97] Fix error in test --- modules/imgproc/test/ocl/test_filter2d.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/imgproc/test/ocl/test_filter2d.cpp b/modules/imgproc/test/ocl/test_filter2d.cpp index 484080df44..54d65459c5 100644 --- a/modules/imgproc/test/ocl/test_filter2d.cpp +++ b/modules/imgproc/test/ocl/test_filter2d.cpp @@ -81,8 +81,7 @@ PARAM_TEST_CASE(Filter2D, MatDepth, Channels, BorderType, bool, bool) Mat temp = randomMat(ksize, CV_MAKE_TYPE(((CV_64F == CV_MAT_DEPTH(type)) ? CV_64F : CV_32F), 1), -MAX_VALUE, MAX_VALUE); cv::normalize(temp, kernel, 1.0, 0.0, NORM_L1); - //Size roiSize = randomSize(ksize.width, MAX_VALUE, ksize.height, MAX_VALUE); - Size roiSize(1024, 1024); + Size roiSize = randomSize(ksize.width, MAX_VALUE, ksize.height, MAX_VALUE); Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE); From 1015c5c24d3695dae8f26925ae1d1fd8402a9a01 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Wed, 11 Dec 2013 15:08:49 +0400 Subject: [PATCH 97/97] fixed facedetect sample --- samples/ocl/facedetect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/ocl/facedetect.cpp b/samples/ocl/facedetect.cpp index b452ab8d89..fd570b5154 100644 --- a/samples/ocl/facedetect.cpp +++ b/samples/ocl/facedetect.cpp @@ -196,7 +196,7 @@ static void detectFaces(std::string fileName) d_img.upload(img); std::vector oclfaces; - cascade.detectMultiScale(d_img, oclfaces, 1.1, 3, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30), Size(0, 0)); + cascade.detectMultiScale(d_img, oclfaces, 1.1, 3, 0 | CASCADE_SCALE_IMAGE, Size(30, 30), Size(0, 0)); for(unsigned int i = 0; i