diff --git a/.gitignore b/.gitignore index 3161cea79..5c1b70773 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ tegra/ tags build/ Thumbs.db +*.autosave diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 5556d52e1..4956edf91 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -33,6 +33,7 @@ # # ocv_add_accuracy_tests() # ocv_add_perf_tests() +# ocv_add_samples() # # # If module have no "extra" then you can define it in one line: @@ -581,6 +582,7 @@ macro(ocv_define_module module_name) ocv_add_accuracy_tests() ocv_add_perf_tests() + ocv_add_samples() endmacro() # ensures that all passed modules are available @@ -725,6 +727,48 @@ function(ocv_add_accuracy_tests) endif() endfunction() +function(ocv_add_samples) + set(samples_path "${CMAKE_CURRENT_SOURCE_DIR}/samples") + string(REGEX REPLACE "^opencv_" "" module_id ${the_module}) + + if(BUILD_EXAMPLES AND EXISTS "${samples_path}") + set(samples_deps ${the_module} ${OPENCV_MODULE_${the_module}_DEPS} opencv_highgui ${ARGN}) + ocv_check_dependencies(${samples_deps}) + + if(OCV_DEPENDENCIES_FOUND) + file(GLOB sample_sources "${samples_path}/*.cpp") + ocv_include_modules(${OPENCV_MODULE_${the_module}_DEPS}) + + foreach(source ${sample_sources}) + get_filename_component(name "${source}" NAME_WE) + set(the_target "example_${module_id}_${name}") + + add_executable(${the_target} "${source}") + target_link_libraries(${the_target} ${samples_deps}) + + set_target_properties(${the_target} PROPERTIES PROJECT_LABEL "(sample) ${name}") + + if(ENABLE_SOLUTION_FOLDERS) + set_target_properties(${the_target} PROPERTIES + OUTPUT_NAME "${module_id}-example-${name}" + FOLDER "samples/${module_id}") + endif() + + if(WIN32) + install(TARGETS ${the_target} RUNTIME DESTINATION "samples/${module_id}" COMPONENT main) + endif() + endforeach() + endif() + endif() + + if(INSTALL_C_EXAMPLES AND NOT WIN32 AND EXISTS "${samples_path}") + file(GLOB sample_files "${samples_path}/*") + install(FILES ${sample_files} + DESTINATION share/OpenCV/samples/${module_id} + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) + endif() +endfunction() + # internal macro; finds all link dependencies of the module # should be used at the end of CMake processing macro(__ocv_track_module_link_dependencies the_module optkind) diff --git a/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.rst b/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.rst index ecd4ba219..96257683e 100644 --- a/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.rst +++ b/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.rst @@ -40,7 +40,7 @@ Code * Display the detected circle in a window. .. |TutorialHoughCirclesSimpleDownload| replace:: here - .. _TutorialHoughCirclesSimpleDownload: http://code.opencv.org/projects/opencv/repository/revisions/master/raw/samples/cpp/houghlines.cpp + .. _TutorialHoughCirclesSimpleDownload: http://code.opencv.org/projects/opencv/repository/revisions/master/raw/samples/cpp/houghcircles.cpp .. |TutorialHoughCirclesFancyDownload| replace:: here .. _TutorialHoughCirclesFancyDownload: http://code.opencv.org/projects/opencv/repository/revisions/master/raw/samples/cpp/tutorial_code/ImgTrans/HoughCircle_Demo.cpp diff --git a/modules/contrib/doc/facerec/facerec_api.rst b/modules/contrib/doc/facerec/facerec_api.rst index 4c48787db..c2c7f56d0 100644 --- a/modules/contrib/doc/facerec/facerec_api.rst +++ b/modules/contrib/doc/facerec/facerec_api.rst @@ -70,6 +70,8 @@ Moreover every :ocv:class:`FaceRecognizer` supports the: * **Loading/Saving** the model state from/to a given XML or YAML. +.. note:: When using the FaceRecognizer interface in combination with Python, please stick to Python 2. Some underlying scripts like create_csv will not work in other versions, like Python 3. + Setting the Thresholds +++++++++++++++++++++++ diff --git a/modules/flann/include/opencv2/flann/any.h b/modules/flann/include/opencv2/flann/any.h index 4042db67c..070d5a421 100644 --- a/modules/flann/include/opencv2/flann/any.h +++ b/modules/flann/include/opencv2/flann/any.h @@ -257,8 +257,7 @@ public: const T& cast() const { if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast(); - void* obj = const_cast(object); - T* r = reinterpret_cast(policy->get_value(&obj)); + T* r = reinterpret_cast(policy->get_value(const_cast(&object))); return *r; } diff --git a/modules/gpuwarping/src/cuda/resize.cu b/modules/gpuwarping/src/cuda/resize.cu index 037718980..94422db9d 100644 --- a/modules/gpuwarping/src/cuda/resize.cu +++ b/modules/gpuwarping/src/cuda/resize.cu @@ -194,7 +194,7 @@ namespace cv { namespace gpu { namespace cudev } template - void call_resize_nearest_tex(const PtrStepSz& src, const PtrStepSz& srcWhole, int yoff, int xoff, const PtrStepSz& dst, float fy, float fx) + void call_resize_nearest_tex(const PtrStepSz& /*src*/, const PtrStepSz& srcWhole, int yoff, int xoff, const PtrStepSz& dst, float fy, float fx) { const dim3 block(32, 8); const dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y)); @@ -301,7 +301,7 @@ namespace cv { namespace gpu { namespace cudev template struct ResizeNearestDispatcher { - static void call(const PtrStepSz& src, const PtrStepSz& srcWhole, int yoff, int xoff, const PtrStepSz& dst, float fy, float fx, cudaStream_t stream) + static void call(const PtrStepSz& src, const PtrStepSz& /*srcWhole*/, int /*yoff*/, int /*xoff*/, const PtrStepSz& dst, float fy, float fx, cudaStream_t stream) { call_resize_nearest_glob(src, dst, fy, fx, stream); } diff --git a/modules/imgproc/doc/filtering.rst b/modules/imgproc/doc/filtering.rst index 37bfe9c10..d019136fa 100755 --- a/modules/imgproc/doc/filtering.rst +++ b/modules/imgproc/doc/filtering.rst @@ -412,6 +412,28 @@ http://www.dai.ed.ac.uk/CVonline/LOCAL\_COPIES/MANDUCHI1/Bilateral\_Filtering.ht This filter does not work inplace. +adaptiveBilateralFilter +----------------------- +Applies the adaptive bilateral filter to an image. + +.. ocv:function:: void adaptiveBilateralFilter( InputArray src, OutputArray dst, Size ksize, double sigmaSpace, Point anchor=Point(-1, -1), int borderType=BORDER_DEFAULT ) + +.. ocv:pyfunction:: cv2.adaptiveBilateralFilter(src, ksize, sigmaSpace[, dst[, anchor[, borderType]]]) -> dst + + :param src: Source 8-bit, 1-channel or 3-channel image. + + :param dst: Destination image of the same size and type as ``src`` . + + :param ksize: filter kernel size. + + :param sigmaSpace: Filter sigma in the coordinate space. It has similar meaning with ``sigmaSpace`` in ``bilateralFilter``. + + :param anchor: anchor point; default value ``Point(-1,-1)`` means that the anchor is at the kernel center. Only default value is supported now. + + :param borderType: border mode used to extrapolate pixels outside of the image. + +The function applies adaptive bilateral filtering to the input image. This filter is similar to ``bilateralFilter``, in that dissimilarity from and distance to the center pixel is punished. Instead of using ``sigmaColor``, we employ the variance of pixel values in the neighbourhood. + blur diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 55816ccb7..e380af8c8 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -1061,6 +1061,11 @@ CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT ); +//! smooths the image using adaptive bilateral filter +CV_EXPORTS_W void adaptiveBilateralFilter( InputArray src, OutputArray dst, Size ksize, + double sigmaSpace, Point anchor=Point(-1, -1), + int borderType=BORDER_DEFAULT ); + //! smooths the image using the box filter. Each pixel is processed in O(1) time CV_EXPORTS_W void boxFilter( InputArray src, OutputArray dst, int ddepth, Size ksize, Point anchor = Point(-1,-1), diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index e8556d460..14703cce2 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -254,19 +254,19 @@ bool CvtColorIPPLoopCopy(Mat& src, Mat& dst, const Cvt& cvt) return ok; } -IppStatus __stdcall ippiSwapChannels_8u_C3C4Rf(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, +static IppStatus CV_STDCALL ippiSwapChannels_8u_C3C4Rf(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, IppiSize roiSize, const int *dstOrder) { return ippiSwapChannels_8u_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP8u); } -IppStatus __stdcall ippiSwapChannels_16u_C3C4Rf(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, +static IppStatus CV_STDCALL ippiSwapChannels_16u_C3C4Rf(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep, IppiSize roiSize, const int *dstOrder) { return ippiSwapChannels_16u_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP16u); } -IppStatus __stdcall ippiSwapChannels_32f_C3C4Rf(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, +static IppStatus CV_STDCALL ippiSwapChannels_32f_C3C4Rf(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, IppiSize roiSize, const int *dstOrder) { return ippiSwapChannels_32f_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP32f); diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index 32a1517db..9e2048407 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -50,9 +50,73 @@ #include #include +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +static IppStatus sts = ippInit(); +#endif + namespace cv { +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + typedef IppStatus (CV_STDCALL* ippiSetFunc)(const void*, void *, int, IppiSize); + typedef IppStatus (CV_STDCALL* ippiWarpPerspectiveBackFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [3][3], int); + typedef IppStatus (CV_STDCALL* ippiWarpAffineBackFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [2][3], int); + typedef IppStatus (CV_STDCALL* ippiResizeSqrPixelFunc)(const void*, IppiSize, int, IppiRect, void*, int, IppiRect, double, double, double, double, int, Ipp8u *); + + template + bool IPPSetSimple(cv::Scalar value, void *dataPointer, int step, IppiSize &size, ippiSetFunc func) + { + Type values[channels]; + for( int i = 0; i < channels; i++ ) + values[i] = (Type)value[i]; + return func(values, dataPointer, step, size) >= 0; + } + + bool IPPSet(const cv::Scalar &value, void *dataPointer, int step, IppiSize &size, int channels, int depth) + { + if( channels == 1 ) + { + switch( depth ) + { + case CV_8U: + return ippiSet_8u_C1R((Ipp8u)value[0], (Ipp8u *)dataPointer, step, size) >= 0; + case CV_16U: + return ippiSet_16u_C1R((Ipp16u)value[0], (Ipp16u *)dataPointer, step, size) >= 0; + case CV_32F: + return ippiSet_32f_C1R((Ipp32f)value[0], (Ipp32f *)dataPointer, step, size) >= 0; + } + } + else + { + if( channels == 3 ) + { + switch( depth ) + { + case CV_8U: + return IPPSetSimple<3, Ipp8u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_8u_C3R); + case CV_16U: + return IPPSetSimple<3, Ipp16u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_16u_C3R); + case CV_32F: + return IPPSetSimple<3, Ipp32f>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_32f_C3R); + } + } + else if( channels == 4 ) + { + switch( depth ) + { + case CV_8U: + return IPPSetSimple<4, Ipp8u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_8u_C4R); + case CV_16U: + return IPPSetSimple<4, Ipp16u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_16u_C4R); + case CV_32F: + return IPPSetSimple<4, Ipp32f>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_32f_C4R); + } + } + } + return false; + } +#endif + /************** interpolation formulas and tables ***************/ const int INTER_RESIZE_COEF_BITS=11; @@ -1795,6 +1859,45 @@ static int computeResizeAreaTab( int ssize, int dsize, int cn, double scale, Dec return k; } +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +class IPPresizeInvoker : + public ParallelLoopBody +{ +public: + IPPresizeInvoker(Mat &_src, Mat &_dst, double &_inv_scale_x, double &_inv_scale_y, int _mode, ippiResizeSqrPixelFunc _func, bool *_ok) : + ParallelLoopBody(), src(_src), dst(_dst), inv_scale_x(_inv_scale_x), inv_scale_y(_inv_scale_y), mode(_mode), func(_func), ok(_ok) + { + *ok = true; + } + + virtual void operator() (const Range& range) const + { + int cn = src.channels(); + IppiRect srcroi = { 0, range.start, src.cols, range.end - range.start }; + int dsty = CV_IMIN(cvRound(range.start * inv_scale_y), dst.rows); + int dstwidth = CV_IMIN(cvRound(src.cols * inv_scale_x), dst.cols); + int dstheight = CV_IMIN(cvRound(range.end * inv_scale_y), dst.rows); + IppiRect dstroi = { 0, dsty, dstwidth, dstheight - dsty }; + int bufsize; + ippiResizeGetBufSize( srcroi, dstroi, cn, mode, &bufsize ); + Ipp8u *buf; + buf = ippsMalloc_8u( bufsize ); + IppStatus sts; + if( func( src.data, ippiSize(src.cols, src.rows), (int)src.step[0], srcroi, dst.data, (int)dst.step[0], dstroi, inv_scale_x, inv_scale_y, 0, 0, mode, buf ) < 0 ) + *ok = false; + ippsFree(buf); + } +private: + Mat &src; + Mat &dst; + double inv_scale_x; + double inv_scale_y; + int mode; + ippiResizeSqrPixelFunc func; + bool *ok; + const IPPresizeInvoker& operator= (const IPPresizeInvoker&); +}; +#endif } @@ -1937,6 +2040,34 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize, double scale_x = 1./inv_scale_x, scale_y = 1./inv_scale_y; int k, sx, sy, dx, dy; +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + int mode = interpolation == INTER_LINEAR ? IPPI_INTER_LINEAR : 0; + int type = src.type(); + ippiResizeSqrPixelFunc ippFunc = + type == CV_8UC1 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_8u_C1R : + type == CV_8UC3 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_8u_C3R : + type == CV_8UC4 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_8u_C4R : + type == CV_16UC1 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16u_C1R : + type == CV_16UC3 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16u_C3R : + type == CV_16UC4 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16u_C4R : + type == CV_16SC1 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16s_C1R : + type == CV_16SC3 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16s_C3R : + type == CV_16SC4 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_16s_C4R : + type == CV_32FC1 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_32f_C1R : + type == CV_32FC3 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_32f_C3R : + type == CV_32FC4 ? (ippiResizeSqrPixelFunc)ippiResizeSqrPixel_32f_C4R : + 0; + if( ippFunc && mode != 0 ) + { + bool ok; + Range range(0, src.rows); + IPPresizeInvoker invoker(src, dst, inv_scale_x, inv_scale_y, mode, ippFunc, &ok); + parallel_for_(range, invoker, dst.total()/(double)(1<<16)); + if( ok ) + return; + } +#endif + if( interpolation == INTER_NEAREST ) { resizeNN( src, dst, inv_scale_x, inv_scale_y ); @@ -3446,6 +3577,49 @@ private: double *M; }; +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +class IPPwarpAffineInvoker : + public ParallelLoopBody +{ +public: + IPPwarpAffineInvoker(Mat &_src, Mat &_dst, double (&_coeffs)[2][3], int &_interpolation, int &_borderType, const Scalar &_borderValue, ippiWarpAffineBackFunc _func, bool *_ok) : + ParallelLoopBody(), src(_src), dst(_dst), mode(_interpolation), coeffs(_coeffs), borderType(_borderType), borderValue(_borderValue), func(_func), ok(_ok) + { + *ok = true; + } + + virtual void operator() (const Range& range) const + { + IppiSize srcsize = { src.cols, src.rows }; + IppiRect srcroi = { 0, 0, src.cols, src.rows }; + IppiRect dstroi = { 0, range.start, dst.cols, range.end - range.start }; + int cnn = src.channels(); + if( borderType == BORDER_CONSTANT ) + { + IppiSize setSize = { dst.cols, range.end - range.start }; + void *dataPointer = dst.data + dst.step[0] * range.start; + if( !IPPSet( borderValue, dataPointer, (int)dst.step[0], setSize, cnn, src.depth() ) ) + { + *ok = false; + return; + } + } + if( func( src.data, srcsize, (int)src.step[0], srcroi, dst.data, (int)dst.step[0], dstroi, coeffs, mode ) < 0) ////Aug 2013: problem in IPP 7.1, 8.0 : sometimes function return ippStsCoeffErr + *ok = false; + } +private: + Mat &src; + Mat &dst; + double (&coeffs)[2][3]; + int mode; + int borderType; + Scalar borderValue; + ippiWarpAffineBackFunc func; + bool *ok; + const IPPwarpAffineInvoker& operator= (const IPPwarpAffineInvoker&); +}; +#endif + } @@ -3492,6 +3666,50 @@ void cv::warpAffine( InputArray _src, OutputArray _dst, const int AB_BITS = MAX(10, (int)INTER_BITS); const int AB_SCALE = 1 << AB_BITS; +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + int depth = src.depth(); + int channels = src.channels(); + if( ( depth == CV_8U || depth == CV_16U || depth == CV_32F ) && + ( channels == 1 || channels == 3 || channels == 4 ) && + ( borderType == cv::BORDER_TRANSPARENT || ( borderType == cv::BORDER_CONSTANT ) ) ) + { + int type = src.type(); + ippiWarpAffineBackFunc ippFunc = + type == CV_8UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C1R : + type == CV_8UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C3R : + type == CV_8UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C4R : + type == CV_16UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C1R : + type == CV_16UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C3R : + type == CV_16UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C4R : + type == CV_32FC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C1R : + type == CV_32FC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C3R : + type == CV_32FC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C4R : + 0; + int mode = + flags == INTER_LINEAR ? IPPI_INTER_LINEAR : + flags == INTER_NEAREST ? IPPI_INTER_NN : + flags == INTER_CUBIC ? IPPI_INTER_CUBIC : + 0; + if( mode && ippFunc ) + { + double coeffs[2][3]; + for( int i = 0; i < 2; i++ ) + { + for( int j = 0; j < 3; j++ ) + { + coeffs[i][j] = matM.at(i, j); + } + } + bool ok; + Range range(0, dst.rows); + IPPwarpAffineInvoker invoker(src, dst, coeffs, mode, borderType, borderValue, ippFunc, &ok); + parallel_for_(range, invoker, dst.total()/(double)(1<<16)); + if( ok ) + return; + } + } +#endif + for( x = 0; x < dst.cols; x++ ) { adelta[x] = saturate_cast(M[0]*x*AB_SCALE); @@ -3599,6 +3817,50 @@ private: Scalar borderValue; }; +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +class IPPwarpPerspectiveInvoker : + public ParallelLoopBody +{ +public: + IPPwarpPerspectiveInvoker(Mat &_src, Mat &_dst, double (&_coeffs)[3][3], int &_interpolation, int &_borderType, const Scalar &_borderValue, ippiWarpPerspectiveBackFunc _func, bool *_ok) : + ParallelLoopBody(), src(_src), dst(_dst), mode(_interpolation), coeffs(_coeffs), borderType(_borderType), borderValue(_borderValue), func(_func), ok(_ok) + { + *ok = true; + } + + virtual void operator() (const Range& range) const + { + IppiSize srcsize = {src.cols, src.rows}; + IppiRect srcroi = {0, 0, src.cols, src.rows}; + IppiRect dstroi = {0, range.start, dst.cols, range.end - range.start}; + int cnn = src.channels(); + + if( borderType == BORDER_CONSTANT ) + { + IppiSize setSize = {dst.cols, range.end - range.start}; + void *dataPointer = dst.data + dst.step[0] * range.start; + if( !IPPSet( borderValue, dataPointer, (int)dst.step[0], setSize, cnn, src.depth() ) ) + { + *ok = false; + return; + } + } + if( func(src.data, srcsize, (int)src.step[0], srcroi, dst.data, (int)dst.step[0], dstroi, coeffs, mode) < 0) + *ok = false; + } +private: + Mat &src; + Mat &dst; + double (&coeffs)[3][3]; + int mode; + int borderType; + const Scalar borderValue; + ippiWarpPerspectiveBackFunc func; + bool *ok; + const IPPwarpPerspectiveInvoker& operator= (const IPPwarpPerspectiveInvoker&); +}; +#endif + } void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0, @@ -3629,6 +3891,50 @@ void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0, if( !(flags & WARP_INVERSE_MAP) ) invert(matM, matM); +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + int depth = src.depth(); + int channels = src.channels(); + if( ( depth == CV_8U || depth == CV_16U || depth == CV_32F ) && + ( channels == 1 || channels == 3 || channels == 4 ) && + ( borderType == cv::BORDER_TRANSPARENT || borderType == cv::BORDER_CONSTANT ) ) + { + int type = src.type(); + ippiWarpPerspectiveBackFunc ippFunc = + type == CV_8UC1 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_8u_C1R : + type == CV_8UC3 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_8u_C3R : + type == CV_8UC4 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_8u_C4R : + type == CV_16UC1 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_16u_C1R : + type == CV_16UC3 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_16u_C3R : + type == CV_16UC4 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_16u_C4R : + type == CV_32FC1 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_32f_C1R : + type == CV_32FC3 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_32f_C3R : + type == CV_32FC4 ? (ippiWarpPerspectiveBackFunc)ippiWarpPerspectiveBack_32f_C4R : + 0; + int mode = + flags == INTER_LINEAR ? IPPI_INTER_LINEAR : + flags == INTER_NEAREST ? IPPI_INTER_NN : + flags == INTER_CUBIC ? IPPI_INTER_CUBIC : + 0; + if( mode && ippFunc ) + { + double coeffs[3][3]; + for( int i = 0; i < 3; i++ ) + { + for( int j = 0; j < 3; j++ ) + { + coeffs[i][j] = matM.at(i, j); + } + } + bool ok; + Range range(0, dst.rows); + IPPwarpPerspectiveInvoker invoker(src, dst, coeffs, mode, borderType, borderValue, ippFunc, &ok); + parallel_for_(range, invoker, dst.total()/(double)(1<<16)); + if( ok ) + return; + } + } +#endif + Range range(0, dst.rows); warpPerspectiveInvoker invoker(src, dst, M, interpolation, borderType, borderValue); parallel_for_(range, invoker, dst.total()/(double)(1<<16)); diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 33ddcf76c..845e00124 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1213,11 +1213,10 @@ static bool IPPMorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kerne } static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst, - InputArray _kernel, - const Point &anchor, int iterations, + const Mat& _kernel, Point anchor, int iterations, int borderType, const Scalar &borderValue) { - Mat src = _src.getMat(), kernel = _kernel.getMat(); + Mat src = _src.getMat(), kernel = _kernel; if( !( src.depth() == CV_8U || src.depth() == CV_32F ) || ( iterations > 1 ) || !( borderType == cv::BORDER_REPLICATE || (borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue()) ) || !( op == MORPH_DILATE || op == MORPH_ERODE) ) @@ -1248,9 +1247,6 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst, } Size ksize = kernel.data ? kernel.size() : Size(3,3); - Point normanchor = normalizeAnchor(anchor, ksize); - - CV_Assert( normanchor.inside(Rect(0, 0, ksize.width, ksize.height)) ); _dst.create( src.size(), src.type() ); Mat dst = _dst.getMat(); @@ -1265,7 +1261,7 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst, if( !kernel.data ) { ksize = Size(1+iterations*2,1+iterations*2); - normanchor = Point(iterations, iterations); + anchor = Point(iterations, iterations); rectKernel = true; iterations = 1; } @@ -1273,7 +1269,7 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst, { ksize = Size(ksize.width + (iterations-1)*(ksize.width-1), ksize.height + (iterations-1)*(ksize.height-1)), - normanchor = Point(normanchor.x*iterations, normanchor.y*iterations); + anchor = Point(anchor.x*iterations, anchor.y*iterations); kernel = Mat(); rectKernel = true; iterations = 1; @@ -1283,7 +1279,7 @@ static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst, if( iterations > 1 ) return false; - return IPPMorphReplicate( op, src, dst, kernel, ksize, normanchor, rectKernel ); + return IPPMorphReplicate( op, src, dst, kernel, ksize, anchor, rectKernel ); } #endif @@ -1292,18 +1288,19 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { - -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - if( IPPMorphOp(op, _src, _dst, _kernel, anchor, iterations, borderType, borderValue) ) - return; -#endif - - Mat src = _src.getMat(), kernel = _kernel.getMat(); + Mat kernel = _kernel.getMat(); Size ksize = kernel.data ? kernel.size() : Size(3,3); anchor = normalizeAnchor(anchor, ksize); CV_Assert( anchor.inside(Rect(0, 0, ksize.width, ksize.height)) ); +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) + if( IPPMorphOp(op, _src, _dst, kernel, anchor, iterations, borderType, borderValue) ) + return; +#endif + + Mat src = _src.getMat(); + _dst.create( src.size(), src.type() ); Mat dst = _dst.getMat(); diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index a4c478a2c..4c53e3345 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1879,6 +1879,41 @@ private: float *space_weight, *color_weight; }; +#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +class IPPBilateralFilter_8u_Invoker : + public ParallelLoopBody +{ +public: + IPPBilateralFilter_8u_Invoker(Mat &_src, Mat &_dst, double _sigma_color, double _sigma_space, int _radius, bool *_ok) : + ParallelLoopBody(), src(_src), dst(_dst), sigma_color(_sigma_color), sigma_space(_sigma_space), radius(_radius), ok(_ok) + { + *ok = true; + } + + virtual void operator() (const Range& range) const + { + int d = radius * 2 + 1; + IppiSize kernel = {d, d}; + IppiSize roi={dst.cols, range.end - range.start}; + int bufsize=0; + ippiFilterBilateralGetBufSize_8u_C1R( ippiFilterBilateralGauss, roi, kernel, &bufsize); + AutoBuffer buf(bufsize); + IppiFilterBilateralSpec *pSpec = (IppiFilterBilateralSpec *)alignPtr(&buf[0], 32); + ippiFilterBilateralInit_8u_C1R( ippiFilterBilateralGauss, kernel, (Ipp32f)sigma_color, (Ipp32f)sigma_space, 1, pSpec ); + if( ippiFilterBilateral_8u_C1R( src.ptr(range.start) + radius * ((int)src.step[0] + 1), (int)src.step[0], dst.ptr(range.start), (int)dst.step[0], roi, kernel, pSpec ) < 0) + *ok = false; + } +private: + Mat &src; + Mat &dst; + double sigma_color; + double sigma_space; + int radius; + bool *ok; + const IPPBilateralFilter_8u_Invoker& operator= (const IPPBilateralFilter_8u_Invoker&); +}; +#endif + static void bilateralFilter_8u( const Mat& src, Mat& dst, int d, double sigma_color, double sigma_space, @@ -1908,32 +1943,19 @@ bilateralFilter_8u( const Mat& src, Mat& dst, int d, radius = MAX(radius, 1); d = radius*2 + 1; -#if 0 && defined HAVE_IPP && (IPP_VERSION_MAJOR >= 7) - if(cn == 1) - { - IppiSize kernel = {d, d}; - IppiSize roi={src.cols, src.rows}; - int bufsize=0; - ippiFilterBilateralGetBufSize_8u_C1R( ippiFilterBilateralGauss, roi, kernel, &bufsize); - AutoBuffer buf(bufsize+128); - IppiFilterBilateralSpec *pSpec = (IppiFilterBilateralSpec *)alignPtr(&buf[0], 32); - ippiFilterBilateralInit_8u_C1R( ippiFilterBilateralGauss, kernel, sigma_color*sigma_color, sigma_space*sigma_space, 1, pSpec ); - Mat tsrc; - const Mat* psrc = &src; - if( src.data == dst.data ) - { - src.copyTo(tsrc); - psrc = &tsrc; - } - if( ippiFilterBilateral_8u_C1R(psrc->data, (int)psrc->step[0], - dst.data, (int)dst.step[0], - roi, kernel, pSpec) >= 0 ) - return; - } -#endif Mat temp; copyMakeBorder( src, temp, radius, radius, radius, radius, borderType ); +#if defined HAVE_IPP && (IPP_VERSION_MAJOR >= 7) + if( cn == 1 ) + { + bool ok; + IPPBilateralFilter_8u_Invoker body(temp, dst, sigma_color * sigma_color, sigma_space * sigma_space, radius, &ok ); + parallel_for_(Range(0, dst.rows), body, dst.total()/(double)(1<<16)); + if( ok ) return; + } +#endif + std::vector _color_weight(cn*256); std::vector _space_weight(d*d); std::vector _space_ofs(d*d); @@ -2258,6 +2280,236 @@ void cv::bilateralFilter( InputArray _src, OutputArray _dst, int d, "Bilateral filtering is only implemented for 8u and 32f images" ); } + +/****************************************************************************************\ + Adaptive Bilateral Filtering +\****************************************************************************************/ + +namespace cv +{ +#define CALCVAR 1 +#define FIXED_WEIGHT 0 + +class adaptiveBilateralFilter_8u_Invoker : + public ParallelLoopBody +{ +public: + adaptiveBilateralFilter_8u_Invoker(Mat& _dest, const Mat& _temp, Size _ksize, double _sigma_space, Point _anchor) : + temp(&_temp), dest(&_dest), ksize(_ksize), sigma_space(_sigma_space), anchor(_anchor) + { + if( sigma_space <= 0 ) + sigma_space = 1; + CV_Assert((ksize.width & 1) && (ksize.height & 1)); + space_weight.resize(ksize.width * ksize.height); + double sigma2 = sigma_space * sigma_space; + int idx = 0; + int w = ksize.width / 2; + int h = ksize.height / 2; + for(int y=-h; y<=h; y++) + for(int x=-w; x<=w; x++) + { + space_weight[idx++] = (float)(sigma2 / (sigma2 + x * x + y * y)); + } + } + virtual void operator()(const Range& range) const + { + int cn = dest->channels(); + int anX = anchor.x; + + const uchar *tptr; + + for(int i = range.start;i < range.end; i++) + { + int startY = i; + if(cn == 1) + { + float var; + int currVal; + int sumVal = 0; + int sumValSqr = 0; + int currValCenter; + int currWRTCenter; + float weight; + float totalWeight = 0.; + float tmpSum = 0.; + + for(int j = 0;j < dest->cols *cn; j+=cn) + { + sumVal = 0; + sumValSqr= 0; + totalWeight = 0.; + tmpSum = 0.; + + // Top row: don't sum the very last element + int startLMJ = 0; + int endLMJ = ksize.width - 1; + int howManyAll = (anX *2 +1)*(ksize.width ); +#if CALCVAR + for(int x = startLMJ; x< endLMJ; x++) + { + tptr = temp->ptr(startY + x) +j; + for(int y=-anX; y<=anX; y++) + { + currVal = tptr[cn*(y+anX)]; + sumVal += currVal; + sumValSqr += (currVal *currVal); + } + } + var = ( (sumValSqr * howManyAll)- sumVal * sumVal ) / ( (float)(howManyAll*howManyAll)); +#else + var = 900.0; +#endif + startLMJ = 0; + endLMJ = ksize.width; + tptr = temp->ptr(startY + (startLMJ+ endLMJ)/2); + currValCenter =tptr[j+cn*anX]; + for(int x = startLMJ; x< endLMJ; x++) + { + tptr = temp->ptr(startY + x) +j; + for(int y=-anX; y<=anX; y++) + { +#if FIXED_WEIGHT + weight = 1.0; +#else + currVal = tptr[cn*(y+anX)]; + currWRTCenter = currVal - currValCenter; + + weight = var / ( var + (currWRTCenter * currWRTCenter) ) * space_weight[x*ksize.width+y+anX];; +#endif + tmpSum += ((float)tptr[cn*(y+anX)] * weight); + totalWeight += weight; + } + } + tmpSum /= totalWeight; + + dest->at(startY ,j)= static_cast(tmpSum); + } + } + else + { + assert(cn == 3); + float var_b, var_g, var_r; + int currVal_b, currVal_g, currVal_r; + int sumVal_b= 0, sumVal_g= 0, sumVal_r= 0; + int sumValSqr_b= 0, sumValSqr_g= 0, sumValSqr_r= 0; + int currValCenter_b= 0, currValCenter_g= 0, currValCenter_r= 0; + int currWRTCenter_b, currWRTCenter_g, currWRTCenter_r; + float weight_b, weight_g, weight_r; + float totalWeight_b= 0., totalWeight_g= 0., totalWeight_r= 0.; + float tmpSum_b = 0., tmpSum_g= 0., tmpSum_r = 0.; + + for(int j = 0;j < dest->cols *cn; j+=cn) + { + sumVal_b= 0, sumVal_g= 0, sumVal_r= 0; + sumValSqr_b= 0, sumValSqr_g= 0, sumValSqr_r= 0; + totalWeight_b= 0., totalWeight_g= 0., totalWeight_r= 0.; + tmpSum_b = 0., tmpSum_g= 0., tmpSum_r = 0.; + + // Top row: don't sum the very last element + int startLMJ = 0; + int endLMJ = ksize.width - 1; + int howManyAll = (anX *2 +1)*(ksize.width); +#if CALCVAR + for(int x = startLMJ; x< endLMJ; x++) + { + tptr = temp->ptr(startY + x) +j; + for(int y=-anX; y<=anX; y++) + { + currVal_b = tptr[cn*(y+anX)], currVal_g = tptr[cn*(y+anX)+1], currVal_r =tptr[cn*(y+anX)+2]; + sumVal_b += currVal_b; + sumVal_g += currVal_g; + sumVal_r += currVal_r; + sumValSqr_b += (currVal_b *currVal_b); + sumValSqr_g += (currVal_g *currVal_g); + sumValSqr_r += (currVal_r *currVal_r); + } + } + var_b = ( (sumValSqr_b * howManyAll)- sumVal_b * sumVal_b ) / ( (float)(howManyAll*howManyAll)); + var_g = ( (sumValSqr_g * howManyAll)- sumVal_g * sumVal_g ) / ( (float)(howManyAll*howManyAll)); + var_r = ( (sumValSqr_r * howManyAll)- sumVal_r * sumVal_r ) / ( (float)(howManyAll*howManyAll)); +#else + var_b = 900.0; var_g = 900.0;var_r = 900.0; +#endif + startLMJ = 0; + endLMJ = ksize.width; + tptr = temp->ptr(startY + (startLMJ+ endLMJ)/2) + j; + currValCenter_b =tptr[cn*anX], currValCenter_g =tptr[cn*anX+1], currValCenter_r =tptr[cn*anX+2]; + for(int x = startLMJ; x< endLMJ; x++) + { + tptr = temp->ptr(startY + x) +j; + for(int y=-anX; y<=anX; y++) + { +#if FIXED_WEIGHT + weight_b = 1.0; + weight_g = 1.0; + weight_r = 1.0; +#else + currVal_b = tptr[cn*(y+anX)];currVal_g=tptr[cn*(y+anX)+1];currVal_r=tptr[cn*(y+anX)+2]; + currWRTCenter_b = currVal_b - currValCenter_b; + currWRTCenter_g = currVal_g - currValCenter_g; + currWRTCenter_r = currVal_r - currValCenter_r; + + float cur_spw = space_weight[x*ksize.width+y+anX]; + weight_b = var_b / ( var_b + (currWRTCenter_b * currWRTCenter_b) ) * cur_spw; + weight_g = var_g / ( var_g + (currWRTCenter_g * currWRTCenter_g) ) * cur_spw; + weight_r = var_r / ( var_r + (currWRTCenter_r * currWRTCenter_r) ) * cur_spw; +#endif + tmpSum_b += ((float)tptr[cn*(y+anX)] * weight_b); + tmpSum_g += ((float)tptr[cn*(y+anX)+1] * weight_g); + tmpSum_r += ((float)tptr[cn*(y+anX)+2] * weight_r); + totalWeight_b += weight_b, totalWeight_g += weight_g, totalWeight_r += weight_r; + } + } + tmpSum_b /= totalWeight_b; + tmpSum_g /= totalWeight_g; + tmpSum_r /= totalWeight_r; + + dest->at(startY,j )= static_cast(tmpSum_b); + dest->at(startY,j+1)= static_cast(tmpSum_g); + dest->at(startY,j+2)= static_cast(tmpSum_r); + } + } + } + } +private: + const Mat *temp; + Mat *dest; + Size ksize; + double sigma_space; + Point anchor; + std::vector space_weight; +}; +static void adaptiveBilateralFilter_8u( const Mat& src, Mat& dst, Size ksize, double sigmaSpace, Point anchor, int borderType ) +{ + 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 ); + Mat temp; + copyMakeBorder(src, temp, anchor.x, anchor.y, anchor.x, anchor.y, borderType); + + adaptiveBilateralFilter_8u_Invoker body(dst, temp, ksize, sigmaSpace, anchor); + parallel_for_(Range(0, size.height), body, dst.total()/(double)(1<<16)); +} +} +void cv::adaptiveBilateralFilter( InputArray _src, OutputArray _dst, Size ksize, + double sigmaSpace, Point anchor, int borderType ) +{ + Mat src = _src.getMat(); + _dst.create(src.size(), src.type()); + Mat dst = _dst.getMat(); + + CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3); + + anchor = normalizeAnchor(anchor,ksize); + if( src.depth() == CV_8U ) + adaptiveBilateralFilter_8u( src, dst, ksize, sigmaSpace, anchor, borderType ); + else + CV_Error( CV_StsUnsupportedFormat, + "Adaptive Bilateral filtering is only implemented for 8u images" ); +} + ////////////////////////////////////////////////////////////////////////////////////////// CV_IMPL void diff --git a/modules/imgproc/test/test_bilateral_filter.cpp b/modules/imgproc/test/test_bilateral_filter.cpp index 2d45fdcf7..0bfc3dc4c 100644 --- a/modules/imgproc/test/test_bilateral_filter.cpp +++ b/modules/imgproc/test/test_bilateral_filter.cpp @@ -251,7 +251,7 @@ namespace cvtest int CV_BilateralFilterTest::validate_test_results(int test_case_index) { - static const double eps = 1; + static const double eps = 4; Mat reference_dst, reference_src; if (_src.depth() == CV_32F) diff --git a/modules/imgproc/test/test_imgwarp.cpp b/modules/imgproc/test/test_imgwarp.cpp index 4ea3b76ba..53f7d5c2f 100644 --- a/modules/imgproc/test/test_imgwarp.cpp +++ b/modules/imgproc/test/test_imgwarp.cpp @@ -1424,7 +1424,7 @@ TEST(Imgproc_fitLine_vector_2d, regression) TEST(Imgproc_fitLine_Mat_2dC2, regression) { - cv::Mat mat1(3, 1, CV_32SC2); + cv::Mat mat1 = Mat::zeros(3, 1, CV_32SC2); std::vector line1; cv::fitLine(mat1, line1, CV_DIST_L2, 0 ,0 ,0); @@ -1444,7 +1444,7 @@ TEST(Imgproc_fitLine_Mat_2dC1, regression) TEST(Imgproc_fitLine_Mat_3dC3, regression) { - cv::Mat mat1(2, 1, CV_32SC3); + cv::Mat mat1 = Mat::zeros(2, 1, CV_32SC3); std::vector line1; cv::fitLine(mat1, line1, CV_DIST_L2, 0 ,0 ,0); @@ -1454,7 +1454,7 @@ TEST(Imgproc_fitLine_Mat_3dC3, regression) TEST(Imgproc_fitLine_Mat_3dC1, regression) { - cv::Mat mat2(2, 3, CV_32SC1); + cv::Mat mat2 = Mat::zeros(2, 3, CV_32SC1); std::vector line2; cv::fitLine(mat2, line2, CV_DIST_L2, 0 ,0 ,0); diff --git a/modules/imgproc/test/test_imgwarp_strict.cpp b/modules/imgproc/test/test_imgwarp_strict.cpp index e04a65a42..76d65b198 100644 --- a/modules/imgproc/test/test_imgwarp_strict.cpp +++ b/modules/imgproc/test/test_imgwarp_strict.cpp @@ -678,8 +678,8 @@ void CV_Remap_Test::generate_test_data() MatIterator_ begin_x = mapx.begin(), end_x = mapx.end(); for ( ; begin_x != end_x; ++begin_x) { - begin_x[0] = static_cast(rng.uniform(static_cast(_n), std::max(src.cols + n - 1, 0))); - begin_x[1] = static_cast(rng.uniform(static_cast(_n), std::max(src.rows + n - 1, 0))); + (*begin_x)[0] = static_cast(rng.uniform(static_cast(_n), std::max(src.cols + n - 1, 0))); + (*begin_x)[1] = static_cast(rng.uniform(static_cast(_n), std::max(src.rows + n - 1, 0))); } if (interpolation != INTER_NEAREST) diff --git a/modules/java/android_test/AndroidManifest.xml b/modules/java/android_test/AndroidManifest.xml index dfe25fff0..81f2bc134 100644 --- a/modules/java/android_test/AndroidManifest.xml +++ b/modules/java/android_test/AndroidManifest.xml @@ -3,7 +3,7 @@ package="org.opencv.test" android:versionCode="1" android:versionName="1.0"> - +