diff --git a/.gitignore b/.gitignore index 3161cea79..de0707a93 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,5 @@ tegra/ .sw[a-z] .*.swp tags -build/ Thumbs.db +*.autosave diff --git a/cmake/OpenCVDetectAndroidSDK.cmake b/cmake/OpenCVDetectAndroidSDK.cmake index 68be77619..0173223d4 100644 --- a/cmake/OpenCVDetectAndroidSDK.cmake +++ b/cmake/OpenCVDetectAndroidSDK.cmake @@ -283,7 +283,7 @@ macro(add_android_project target path) ocv_include_modules_recurse(${android_proj_NATIVE_DEPS}) ocv_include_directories("${path}/jni") - if (NATIVE_APP_GLUE AND 0) + if(NATIVE_APP_GLUE) include_directories(${ANDROID_NDK}/sources/android/native_app_glue) list(APPEND android_proj_jni_files ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) ocv_warnings_disable(CMAKE_C_FLAGS -Wstrict-prototypes -Wunused-parameter -Wmissing-prototypes) diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index bc46c825f..b936065ce 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/bioinspired/src/opencl/retina_kernel.cl b/modules/bioinspired/src/opencl/retina_kernel.cl index 1eac50324..169be4d27 100644 --- a/modules/bioinspired/src/opencl/retina_kernel.cl +++ b/modules/bioinspired/src/opencl/retina_kernel.cl @@ -43,6 +43,9 @@ // //M*/ +//data (which is float) is aligend in 32 bytes +#define WIDTH_MULTIPLE (32 >> 2) + ///////////////////////////////////////////////////////// //******************************************************* // basicretinafilter @@ -116,22 +119,18 @@ kernel void horizontalAnticausalFilter( float4 result_v4 = (float4)(0), out_v4; float result = 0; - // we assume elements_per_row is multple of 4 - for(int i = 0; i < 4; ++ i, -- optr) + // we assume elements_per_row is multple of WIDTH_MULTIPLE + for(int i = 0; i < WIDTH_MULTIPLE; ++ i, -- optr) { - if(i < elements_per_row - cols) - { - *optr = result; - } - else + if(i >= elements_per_row - cols) { result = *optr + _a * result; - *optr = result; } + *optr = result; } result_v4.x = result; optr -= 3; - for(int i = 1; i < elements_per_row / 4; ++i, optr -= 4) + for(int i = WIDTH_MULTIPLE / 4; i < elements_per_row / 4; ++i, optr -= 4) { // shift left, `offset` is type `size_t` so it cannot be negative out_v4 = vload4(0, optr); @@ -223,23 +222,19 @@ kernel void horizontalAnticausalFilter_Irregular( float4 buf_v4, out_v4, res_v4 = (float4)(0); float result = 0; - // we assume elements_per_row is multple of 4 - for(int i = 0; i < 4; ++ i, -- optr, -- bptr) + // we assume elements_per_row is multple of WIDTH_MULTIPLE + for(int i = 0; i < WIDTH_MULTIPLE; ++ i, -- optr, -- bptr) { - if(i < elements_per_row - cols) - { - *optr = result; - } - else + if(i >= elements_per_row - cols) { result = *optr + *bptr * result; - *optr = result; } + *optr = result; } res_v4.x = result; optr -= 3; bptr -= 3; - for(int i = 0; i < elements_per_row / 4 - 1; ++i, optr -= 4, bptr -= 4) + for(int i = WIDTH_MULTIPLE / 4; i < elements_per_row / 4; ++i, optr -= 4, bptr -= 4) { buf_v4 = vload4(0, bptr); out_v4 = vload4(0, optr); diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index f5ccb54a7..1a8777b93 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -262,16 +262,16 @@ CV_EXPORTS Mat findFundamentalMat( InputArray points1, InputArray points2, double param1 = 3., double param2 = 0.99 ); //! finds essential matrix from a set of corresponding 2D points using five-point algorithm -CV_EXPORTS Mat findEssentialMat( InputArray points1, InputArray points2, +CV_EXPORTS_W Mat findEssentialMat( InputArray points1, InputArray points2, double focal = 1.0, Point2d pp = Point2d(0, 0), int method = RANSAC, double prob = 0.999, double threshold = 1.0, OutputArray mask = noArray() ); //! decompose essential matrix to possible rotation matrix and one translation vector -CV_EXPORTS void decomposeEssentialMat( InputArray E, OutputArray R1, OutputArray R2, OutputArray t ); +CV_EXPORTS_W void decomposeEssentialMat( InputArray E, OutputArray R1, OutputArray R2, OutputArray t ); //! recover relative camera pose from a set of corresponding 2D points -CV_EXPORTS int recoverPose( InputArray E, InputArray points1, InputArray points2, +CV_EXPORTS_W int recoverPose( InputArray E, InputArray points1, InputArray points2, OutputArray R, OutputArray t, double focal = 1.0, Point2d pp = Point2d(0, 0), InputOutputArray mask = noArray() ); 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/imgproc/doc/feature_detection.rst b/modules/imgproc/doc/feature_detection.rst index 1c5d29c16..a6d5817dd 100644 --- a/modules/imgproc/doc/feature_detection.rst +++ b/modules/imgproc/doc/feature_detection.rst @@ -496,6 +496,110 @@ And this is the output of the above program in case of the probabilistic Hough t .. image:: pics/houghp.png +.. seealso:: + + :ocv:class:`LineSegmentDetector` + + + +LineSegmentDetector +------------------- +Line segment detector class, following the algorithm described at [Rafael12]_. + +.. ocv:class:: LineSegmentDetector : public Algorithm + + +createLineSegmentDetectorPtr +---------------------------- +Creates a smart pointer to a LineSegmentDetector object and initializes it. + +.. ocv:function:: Ptr createLineSegmentDetectorPtr(int _refine = LSD_REFINE_STD, double _scale = 0.8, double _sigma_scale = 0.6, double _quant = 2.0, double _ang_th = 22.5, double _log_eps = 0, double _density_th = 0.7, int _n_bins = 1024) + + :param _refine: The way found lines will be refined: + + * **LSD_REFINE_NONE** - No refinement applied. + + * **LSD_REFINE_STD** - Standard refinement is applied. E.g. breaking arches into smaller straighter line approximations. + + * **LSD_REFINE_ADV** - Advanced refinement. Number of false alarms is calculated, lines are refined through increase of precision, decrement in size, etc. + + :param scale: The scale of the image that will be used to find the lines. Range (0..1]. + + :param sigma_scale: Sigma for Gaussian filter. It is computed as sigma = _sigma_scale/_scale. + + :param quant: Bound to the quantization error on the gradient norm. + + :param ang_th: Gradient angle tolerance in degrees. + + :param log_eps: Detection threshold: -log10(NFA) > log_eps. Used only when advancent refinement is chosen. + + :param density_th: Minimal density of aligned region points in the enclosing rectangle. + + :param n_bins: Number of bins in pseudo-ordering of gradient modulus. + +The LineSegmentDetector algorithm is defined using the standard values. Only advanced users may want to edit those, as to tailor it for their own application. + + +LineSegmentDetector::detect +--------------------------- +Finds lines in the input image. See the lsd_lines.cpp sample for possible usage. + +.. ocv:function:: void LineSegmentDetector::detect(const InputArray _image, OutputArray _lines, OutputArray width = noArray(), OutputArray prec = noArray(), OutputArray nfa = noArray()) + + :param _image A grayscale (CV_8UC1) input image. + If only a roi needs to be selected, use :: + lsd_ptr->detect(image(roi), lines, ...); + lines += Scalar(roi.x, roi.y, roi.x, roi.y); + + :param lines: A vector of Vec4i elements specifying the beginning and ending point of a line. Where Vec4i is (x1, y1, x2, y2), point 1 is the start, point 2 - end. Returned lines are strictly oriented depending on the gradient. + + :param width: Vector of widths of the regions, where the lines are found. E.g. Width of line. + + :param prec: Vector of precisions with which the lines are found. + + :param nfa: Vector containing number of false alarms in the line region, with precision of 10%. The bigger the value, logarithmically better the detection. + + * -1 corresponds to 10 mean false alarms + + * 0 corresponds to 1 mean false alarm + + * 1 corresponds to 0.1 mean false alarms + + This vector will be calculated only when the objects type is LSD_REFINE_ADV. + +This is the output of the default parameters of the algorithm on the above shown image. + +.. image:: pics/building_lsd.png + +.. note:: + + * An example using the LineSegmentDetector can be found at opencv_source_code/samples/cpp/lsd_lines.cpp + +LineSegmentDetector::drawSegments +--------------------------------- +Draws the line segments on a given image. + +.. ocv:function:: void LineSegmentDetector::drawSegments(InputOutputArray _image, InputArray lines) + + :param image: The image, where the liens will be drawn. Should be bigger or equal to the image, where the lines were found. + + :param lines: A vector of the lines that needed to be drawn. + + +LineSegmentDetector::compareSegments +------------------------------------ +Draws two groups of lines in blue and red, counting the non overlapping (mismatching) pixels. + +.. ocv:function:: int LineSegmentDetector::compareSegments(const Size& size, InputArray lines1, InputArray lines2, InputOutputArray _image = noArray()) + + :param size: The size of the image, where lines1 and lines2 were found. + + :param lines1: The first group of lines that needs to be drawn. It is visualized in blue color. + + :param lines2: The second group of lines. They visualized in red color. + + :param image: Optional image, where the lines will be drawn. The image should be color in order for lines1 and lines2 to be drawn in the above mentioned colors. + preCornerDetect @@ -542,3 +646,5 @@ The corners can be found as local maximums of the functions, as shown below: :: .. [Shi94] J. Shi and C. Tomasi. *Good Features to Track*. Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition, pages 593-600, June 1994. .. [Yuen90] Yuen, H. K. and Princen, J. and Illingworth, J. and Kittler, J., *Comparative study of Hough transform methods for circle finding*. Image Vision Comput. 8 1, pp 71–77 (1990) + +.. [Rafael12] Rafael Grompone von Gioi, Jérémie Jakubowicz, Jean-Michel Morel, and Gregory Randall, LSD: a Line Segment Detector, Image Processing On Line, vol. 2012. http://dx.doi.org/10.5201/ipol.2012.gjmr-lsd 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/doc/pics/building_lsd.png b/modules/imgproc/doc/pics/building_lsd.png new file mode 100644 index 000000000..747029a65 Binary files /dev/null and b/modules/imgproc/doc/pics/building_lsd.png differ diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 55816ccb7..5ff1b7449 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -904,7 +904,7 @@ class LineSegmentDetector : public Algorithm { public: /** - * Detect lines in the input image with the specified ROI. + * Detect lines in the input image. * * @param _image A grayscale(CV_8UC1) input image. * If only a roi needs to be selected, use @@ -913,8 +913,6 @@ public: * @param _lines Return: A vector of Vec4i elements specifying the beginning and ending point of a line. * Where Vec4i is (x1, y1, x2, y2), point 1 is the start, point 2 - end. * Returned lines are strictly oriented depending on the gradient. - * @param _roi Return: ROI of the image, where lines are to be found. If specified, the returning - * lines coordinates are image wise. * @param width Return: Vector of widths of the regions, where the lines are found. E.g. Width of line. * @param prec Return: Vector of precisions with which the lines are found. * @param nfa Return: Vector containing number of false alarms in the line region, with precision of 10%. @@ -935,18 +933,19 @@ public: * Should have the size of the image, where the lines were found * @param lines The lines that need to be drawn */ - virtual void drawSegments(InputOutputArray image, InputArray lines) = 0; + virtual void drawSegments(InputOutputArray _image, InputArray lines) = 0; /** * Draw both vectors on the image canvas. Uses blue for lines 1 and red for lines 2. * - * @param image The image, where lines will be drawn. - * Should have the size of the image, where the lines were found + * @param size The size of the image, where lines were found. * @param lines1 The first lines that need to be drawn. Color - Blue. * @param lines2 The second lines that need to be drawn. Color - Red. + * @param image Optional image, where lines will be drawn. + * Should have the size of the image, where the lines were found * @return The number of mismatching pixels between lines1 and lines2. */ - virtual int compareSegments(const Size& size, InputArray lines1, InputArray lines2, Mat* image = 0) = 0; + virtual int compareSegments(const Size& size, InputArray lines1, InputArray lines2, InputOutputArray _image = noArray()) = 0; virtual ~LineSegmentDetector() {}; }; @@ -1061,6 +1060,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/lsd.cpp b/modules/imgproc/src/lsd.cpp index f468c6187..bb3895448 100644 --- a/modules/imgproc/src/lsd.cpp +++ b/modules/imgproc/src/lsd.cpp @@ -1,5 +1,6 @@ /*M/////////////////////////////////////////////////////////////////////////////////////// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. // // By downloading, copying, installing or using the software you agree to this license. // If you do not agree to this license, do not download, install, @@ -9,8 +10,7 @@ // License Agreement // For Open Source Computer Vision Library // -// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. +// Copyright (C) 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, @@ -185,7 +185,7 @@ public: double _log_eps = 0, double _density_th = 0.7, int _n_bins = 1024); /** - * Detect lines in the input image with the specified ROI. + * Detect lines in the input image. * * @param _image A grayscale(CV_8UC1) input image. * If only a roi needs to be selected, use @@ -194,8 +194,6 @@ public: * @param _lines Return: A vector of Vec4i elements specifying the beginning and ending point of a line. * Where Vec4i is (x1, y1, x2, y2), point 1 is the start, point 2 - end. * Returned lines are strictly oriented depending on the gradient. - * @param _roi Return: ROI of the image, where lines are to be found. If specified, the returning - * lines coordinates are image wise. * @param width Return: Vector of widths of the regions, where the lines are found. E.g. Width of line. * @param prec Return: Vector of precisions with which the lines are found. * @param nfa Return: Vector containing number of false alarms in the line region, with precision of 10%. @@ -216,18 +214,19 @@ public: * Should have the size of the image, where the lines were found * @param lines The lines that need to be drawn */ - void drawSegments(InputOutputArray image, InputArray lines); + void drawSegments(InputOutputArray _image, InputArray lines); /** * Draw both vectors on the image canvas. Uses blue for lines 1 and red for lines 2. * - * @param image The image, where lines will be drawn. - * Should have the size of the image, where the lines were found + * @param size The size of the image, where lines1 and lines2 were found. * @param lines1 The first lines that need to be drawn. Color - Blue. * @param lines2 The second lines that need to be drawn. Color - Red. + * @param image An optional image, where lines will be drawn. + * Should have the size of the image, where the lines were found * @return The number of mismatching pixels between lines1 and lines2. */ - int compareSegments(const Size& size, InputArray lines1, InputArray lines2, Mat* image = 0); + int compareSegments(const Size& size, InputArray lines1, InputArray lines2, InputOutputArray _image = noArray()); private: Mat image; @@ -336,7 +335,7 @@ private: * @param rec Return: The generated rectangle. */ void region2rect(const std::vector& reg, const int reg_size, const double reg_angle, - const double prec, const double p, rect& rec) const; + const double prec, const double p, rect& rec) const; /** * Compute region's angle as the principal inertia axis of the region. @@ -410,7 +409,7 @@ LineSegmentDetectorImpl::LineSegmentDetectorImpl(int _refine, double _scale, dou _n_bins > 0); } -void LineSegmentDetectorImpl::detect(const InputArray _image, OutputArray _lines, +void LineSegmentDetectorImpl::detect(InputArray _image, OutputArray _lines, OutputArray _width, OutputArray _prec, OutputArray _nfa) { Mat_ img = _image.getMat(); @@ -1150,7 +1149,7 @@ inline bool LineSegmentDetectorImpl::isAligned(const int& address, const double& } -void LineSegmentDetectorImpl::drawSegments(InputOutputArray _image, const InputArray lines) +void LineSegmentDetectorImpl::drawSegments(InputOutputArray _image, InputArray lines) { CV_Assert(!_image.empty() && (_image.channels() == 1 || _image.channels() == 3)); @@ -1186,10 +1185,10 @@ void LineSegmentDetectorImpl::drawSegments(InputOutputArray _image, const InputA } -int LineSegmentDetectorImpl::compareSegments(const Size& size, const InputArray lines1, const InputArray lines2, Mat* _image) +int LineSegmentDetectorImpl::compareSegments(const Size& size, InputArray lines1, InputArray lines2, InputOutputArray _image) { Size sz = size; - if (_image && _image->size() != size) sz = _image->size(); + if (_image.needed() && _image.size() != size) sz = _image.size(); CV_Assert(sz.area()); Mat_ I1 = Mat_::zeros(sz); @@ -1219,14 +1218,11 @@ int LineSegmentDetectorImpl::compareSegments(const Size& size, const InputArray bitwise_xor(I1, I2, Ixor); int N = countNonZero(Ixor); - if (_image) + if (_image.needed()) { - Mat Ig; - if (_image->channels() == 1) - { - cvtColor(*_image, *_image, CV_GRAY2BGR); - } - CV_Assert(_image->isContinuous() && I1.isContinuous() && I2.isContinuous()); + CV_Assert(_image.channels() == 3); + Mat img = _image.getMatRef(); + CV_Assert(img.isContinuous() && I1.isContinuous() && I2.isContinuous()); for (unsigned int i = 0; i < I1.total(); ++i) { @@ -1234,11 +1230,12 @@ int LineSegmentDetectorImpl::compareSegments(const Size& size, const InputArray uchar i2 = I2.data[i]; if (i1 || i2) { - _image->data[3*i + 1] = 0; - if (i1) _image->data[3*i] = 255; - else _image->data[3*i] = 0; - if (i2) _image->data[3*i + 2] = 255; - else _image->data[3*i + 2] = 0; + unsigned int base_idx = i * 3; + if (i1) img.data[base_idx] = 255; + else img.data[base_idx] = 0; + img.data[base_idx + 1] = 0; + if (i2) img.data[base_idx + 2] = 255; + else img.data[base_idx + 2] = 0; } } } 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"> - +