diff --git a/cmake/OpenCVFindIPP.cmake b/cmake/OpenCVFindIPP.cmake index b4f3a78f2c..6bcd81d8b4 100644 --- a/cmake/OpenCVFindIPP.cmake +++ b/cmake/OpenCVFindIPP.cmake @@ -151,7 +151,7 @@ macro(ipp_detect_version) if("${name}" STREQUAL "core") # https://github.com/opencv/opencv/pull/19681 if(OPENCV_FORCE_IPP_EXCLUDE_LIBS OR OPENCV_FORCE_IPP_EXCLUDE_LIBS_CORE OR (UNIX AND NOT ANDROID AND NOT APPLE - AND (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|Intel" ) AND NOT OPENCV_SKIP_IPP_EXCLUDE_LIBS_CORE ) diff --git a/cmake/OpenCVFindLibsPerf.cmake b/cmake/OpenCVFindLibsPerf.cmake index 3753084d28..a191afde58 100644 --- a/cmake/OpenCVFindLibsPerf.cmake +++ b/cmake/OpenCVFindLibsPerf.cmake @@ -29,7 +29,7 @@ if(WITH_IPP) if(OPENCV_FORCE_IPP_EXCLUDE_LIBS OR (HAVE_IPP_ICV AND UNIX AND NOT ANDROID AND NOT APPLE - AND (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|Intel" ) AND NOT OPENCV_SKIP_IPP_EXCLUDE_LIBS ) diff --git a/modules/calib3d/include/opencv2/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d.hpp index 95de4ca399..efbbbbc014 100644 --- a/modules/calib3d/include/opencv2/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d.hpp @@ -2690,6 +2690,7 @@ final fundamental matrix. It can be set to something like 1-3, depending on the point localization, image resolution, and the image noise. @param mask Output array of N elements, every element of which is set to 0 for outliers and to 1 for the other points. The array is computed only in the RANSAC and LMedS methods. +@param maxIters The maximum number of robust method iterations. This function estimates essential matrix based on the five-point algorithm solver in @cite Nister03 . @cite SteweniusCFS is also a related. The epipolar geometry is described by the following equation: @@ -2700,10 +2701,22 @@ where \f$E\f$ is an essential matrix, \f$p_1\f$ and \f$p_2\f$ are corresponding second images, respectively. The result of this function may be passed further to decomposeEssentialMat or recoverPose to recover the relative pose between cameras. */ -CV_EXPORTS_W Mat findEssentialMat( InputArray points1, InputArray points2, - InputArray cameraMatrix, int method = RANSAC, - double prob = 0.999, double threshold = 1.0, - OutputArray mask = noArray() ); +CV_EXPORTS_W +Mat findEssentialMat( + InputArray points1, InputArray points2, + InputArray cameraMatrix, int method = RANSAC, + double prob = 0.999, double threshold = 1.0, + int maxIters = 1000, OutputArray mask = noArray() +); + +/** @overload */ +CV_EXPORTS +Mat findEssentialMat( + InputArray points1, InputArray points2, + InputArray cameraMatrix, int method, + double prob, double threshold, + OutputArray mask +); // TODO remove from OpenCV 5.0 /** @overload @param points1 Array of N (N \>= 5) 2D points from the first image. The point coordinates should @@ -2723,6 +2736,7 @@ point localization, image resolution, and the image noise. confidence (probability) that the estimated matrix is correct. @param mask Output array of N elements, every element of which is set to 0 for outliers and to 1 for the other points. The array is computed only in the RANSAC and LMedS methods. +@param maxIters The maximum number of robust method iterations. This function differs from the one above that it computes camera intrinsic matrix from focal length and principal point: @@ -2734,10 +2748,23 @@ f & 0 & x_{pp} \\ 0 & 0 & 1 \end{bmatrix}\f] */ -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() ); +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, int maxIters = 1000, + OutputArray mask = noArray() +); + +/** @overload */ +CV_EXPORTS +Mat findEssentialMat( + InputArray points1, InputArray points2, + double focal, Point2d pp, + int method, double prob, + double threshold, OutputArray mask +); // TODO remove from OpenCV 5.0 /** @brief Calculates an essential matrix from the corresponding points in two images from potentially two different cameras. diff --git a/modules/calib3d/src/five-point.cpp b/modules/calib3d/src/five-point.cpp index f35b7bb4b2..d005248535 100644 --- a/modules/calib3d/src/five-point.cpp +++ b/modules/calib3d/src/five-point.cpp @@ -405,7 +405,8 @@ protected: // Input should be a vector of n 2D points or a Nx2 matrix cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArray _cameraMatrix, - int method, double prob, double threshold, OutputArray _mask) + int method, double prob, double threshold, + int maxIters, OutputArray _mask) { CV_INSTRUMENT_REGION(); @@ -448,20 +449,36 @@ cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArr Mat E; if( method == RANSAC ) - createRANSACPointSetRegistrator(makePtr(), 5, threshold, prob)->run(points1, points2, E, _mask); + createRANSACPointSetRegistrator(makePtr(), 5, threshold, prob, maxIters)->run(points1, points2, E, _mask); else - createLMeDSPointSetRegistrator(makePtr(), 5, prob)->run(points1, points2, E, _mask); + createLMeDSPointSetRegistrator(makePtr(), 5, prob, maxIters)->run(points1, points2, E, _mask); return E; } +cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, InputArray _cameraMatrix, + int method, double prob, double threshold, + OutputArray _mask) +{ + return cv::findEssentialMat(_points1, _points2, _cameraMatrix, method, prob, threshold, 1000, _mask); +} + +cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, double focal, Point2d pp, + int method, double prob, double threshold, int maxIters, OutputArray _mask) +{ + CV_INSTRUMENT_REGION(); + + Mat cameraMatrix = (Mat_(3,3) << focal, 0, pp.x, 0, focal, pp.y, 0, 0, 1); + return cv::findEssentialMat(_points1, _points2, cameraMatrix, method, prob, threshold, maxIters, _mask); +} + cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, double focal, Point2d pp, int method, double prob, double threshold, OutputArray _mask) { CV_INSTRUMENT_REGION(); Mat cameraMatrix = (Mat_(3,3) << focal, 0, pp.x, 0, focal, pp.y, 0, 0, 1); - return cv::findEssentialMat(_points1, _points2, cameraMatrix, method, prob, threshold, _mask); + return cv::findEssentialMat(_points1, _points2, cameraMatrix, method, prob, threshold, 1000, _mask); } cv::Mat cv::findEssentialMat( InputArray _points1, InputArray _points2, diff --git a/modules/calib3d/src/fundam.cpp b/modules/calib3d/src/fundam.cpp index 2ddcabba06..f0a7df605b 100644 --- a/modules/calib3d/src/fundam.cpp +++ b/modules/calib3d/src/fundam.cpp @@ -888,7 +888,7 @@ cv::Mat cv::findFundamentalMat( InputArray _points1, InputArray _points2, if( (method & ~3) == FM_RANSAC && npoints >= 15 ) result = createRANSACPointSetRegistrator(cb, 7, ransacReprojThreshold, confidence, maxIters)->run(m1, m2, F, _mask); else - result = createLMeDSPointSetRegistrator(cb, 7, confidence)->run(m1, m2, F, _mask); + result = createLMeDSPointSetRegistrator(cb, 7, confidence, maxIters)->run(m1, m2, F, _mask); } if( result <= 0 ) diff --git a/modules/core/perf/opencl/perf_arithm.cpp b/modules/core/perf/opencl/perf_arithm.cpp index 9f5f6e9e77..0cbfc2d653 100644 --- a/modules/core/perf/opencl/perf_arithm.cpp +++ b/modules/core/perf/opencl/perf_arithm.cpp @@ -678,7 +678,12 @@ OCL_PERF_TEST_P(SqrtFixture, Sqrt, ::testing::Combine( OCL_TEST_CYCLE() cv::sqrt(src, dst); - if (CV_MAT_DEPTH(type) >= CV_32F) + // To square root 32 bit floats we use native_sqrt, which has implementation + // defined accuracy. We know intel devices have accurate native_sqrt, but + // otherwise stick to a relaxed sanity check. For types larger than 32 bits + // we can do the accuracy check for all devices as normal. + if (CV_MAT_DEPTH(type) > CV_32F || !ocl::useOpenCL() || + ocl::Device::getDefault().isIntel()) SANITY_CHECK(dst, 1e-5, ERROR_RELATIVE); else SANITY_CHECK(dst, 1); diff --git a/modules/features2d/src/blobdetector.cpp b/modules/features2d/src/blobdetector.cpp index d07e8bae83..c2215cd57c 100644 --- a/modules/features2d/src/blobdetector.cpp +++ b/modules/features2d/src/blobdetector.cpp @@ -325,13 +325,19 @@ void SimpleBlobDetectorImpl::detect(InputArray image, std::vector& std::vector < Center > curCenters; findBlobs(grayscaleImage, binarizedImage, curCenters); + if(params.maxThreshold - params.minThreshold <= params.thresholdStep) { + // if the difference between min and max threshold is less than the threshold step + // we're only going to enter the loop once, so we need to add curCenters + // to ensure we still use minDistBetweenBlobs + centers.push_back(curCenters); + } std::vector < std::vector
> newCenters; for (size_t i = 0; i < curCenters.size(); i++) { bool isNew = true; for (size_t j = 0; j < centers.size(); j++) { - double dist = norm(centers[j][ centers[j].size() / 2 ].location - curCenters[i].location); + double dist = norm(centers[j][centers[j].size() / 2 ].location - curCenters[i].location); isNew = dist >= params.minDistBetweenBlobs && dist >= centers[j][ centers[j].size() / 2 ].radius && dist >= curCenters[i].radius; if (!isNew) { diff --git a/modules/features2d/test/test_blobdetector.cpp b/modules/features2d/test/test_blobdetector.cpp new file mode 100644 index 0000000000..56b7145862 --- /dev/null +++ b/modules/features2d/test/test_blobdetector.cpp @@ -0,0 +1,21 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#include "test_precomp.hpp" + +namespace opencv_test { namespace { +TEST(Features2d_BlobDetector, bug_6667) +{ + cv::Mat image = cv::Mat(cv::Size(100, 100), CV_8UC1, cv::Scalar(255, 255, 255)); + cv::circle(image, Point(50, 50), 20, cv::Scalar(0), -1); + SimpleBlobDetector::Params params; + params.minThreshold = 250; + params.maxThreshold = 260; + std::vector keypoints; + + Ptr detector = SimpleBlobDetector::create(params); + detector->detect(image, keypoints); + ASSERT_NE((int) keypoints.size(), 0); +} +}} // namespace diff --git a/modules/imgproc/perf/opencl/perf_imgproc.cpp b/modules/imgproc/perf/opencl/perf_imgproc.cpp index 4b61976553..db4c4ef451 100644 --- a/modules/imgproc/perf/opencl/perf_imgproc.cpp +++ b/modules/imgproc/perf/opencl/perf_imgproc.cpp @@ -166,7 +166,17 @@ OCL_PERF_TEST_P(CornerMinEigenValFixture, CornerMinEigenVal, OCL_TEST_CYCLE() cv::cornerMinEigenVal(src, dst, blockSize, apertureSize, borderType); - SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); +#ifdef HAVE_OPENCL + bool strictCheck = !ocl::useOpenCL() || ocl::Device::getDefault().isIntel(); +#else + bool strictCheck = true; +#endif + + // using native_* OpenCL functions on non-intel devices may lose accuracy + if (strictCheck) + SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); + else + SANITY_CHECK(dst, 0.1, ERROR_RELATIVE); } ///////////// CornerHarris //////////////////////// diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index 7d772d42ef..f57d05faee 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -2190,7 +2190,7 @@ public: int bw = std::min( bw0, dst.cols - x); int bh = std::min( bh0, range.end - y); - Mat _XY(bh, bw, CV_16SC2, XY), matA; + Mat _XY(bh, bw, CV_16SC2, XY); Mat dpart(dst, Rect(x, y, bw, bh)); for( y1 = 0; y1 < bh; y1++ ) @@ -2979,7 +2979,7 @@ public: int bw = std::min( bw0, width - x); int bh = std::min( bh0, range.end - y); // height - Mat _XY(bh, bw, CV_16SC2, XY), matA; + Mat _XY(bh, bw, CV_16SC2, XY); Mat dpart(dst, Rect(x, y, bw, bh)); for( y1 = 0; y1 < bh; y1++ ) diff --git a/modules/imgproc/test/ocl/test_imgproc.cpp b/modules/imgproc/test/ocl/test_imgproc.cpp index 35185d339f..f3e9f4bb20 100644 --- a/modules/imgproc/test/ocl/test_imgproc.cpp +++ b/modules/imgproc/test/ocl/test_imgproc.cpp @@ -234,10 +234,12 @@ OCL_TEST_P(CornerMinEigenVal, Mat) OCL_OFF(cv::cornerMinEigenVal(src_roi, dst_roi, blockSize, apertureSize, borderType)); OCL_ON(cv::cornerMinEigenVal(usrc_roi, udst_roi, blockSize, apertureSize, borderType)); - if (ocl::Device::getDefault().isIntel()) - Near(1e-5, true); + // The corner kernel uses native_sqrt() which has implementation defined accuracy. + // If we're using a CL implementation that isn't intel, test with relaxed accuracy. + if (!ocl::useOpenCL() || ocl::Device::getDefault().isIntel()) + Near(1e-5, true); else - Near(0.1, true); // using native_* OpenCL functions may lose accuracy + Near(0.1, true); } }