diff --git a/modules/imgproc/src/featureselect.cpp b/modules/imgproc/src/featureselect.cpp index 3f54bef61e..fc1b034209 100644 --- a/modules/imgproc/src/featureselect.cpp +++ b/modules/imgproc/src/featureselect.cpp @@ -42,6 +42,8 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" +#include "opencv2/core/openvx/ovx_defs.hpp" + #include #include #include @@ -262,6 +264,95 @@ static bool ocl_goodFeaturesToTrack( InputArray _image, OutputArray _corners, #endif +#ifdef HAVE_OPENVX +struct VxKeypointsComparator +{ + bool operator () (const vx_keypoint_t& a, const vx_keypoint_t& b) + { + return a.strength > b.strength; + } +}; + +static bool openvx_harris(Mat image, OutputArray _corners, + int _maxCorners, double _qualityLevel, double _minDistance, + int _blockSize, double _harrisK) +{ + using namespace ivx; + + if(image.type() != CV_8UC1) return false; + + //OpenVX implementations don't have to provide other sizes + if(!(_blockSize == 3 || _blockSize == 5 || _blockSize == 7)) return false; + + try + { + Context context = Context::create(); + + Image ovxImage = Image::createFromHandle(context, Image::matTypeToFormat(image.type()), + Image::createAddressing(image), image.data); + //The minimum threshold which to eliminate Harris Corner scores (computed using the normalized Sobel kernel). + //set to 0, we'll filter it later by threshold + ivx::Scalar strengthThresh = ivx::Scalar::create(context, 0); + + //The gradient window size to use on the input. + vx_int32 gradientSize = 3; + + //The block window size used to compute the harris corner score + vx_int32 blockSize = _blockSize; + + //The scalar sensitivity threshold k from the Harris-Stephens equation + ivx::Scalar sensivity = ivx::Scalar::create(context, _harrisK); + + //The radial Euclidean distance for non-maximum suppression + ivx::Scalar minDistance = ivx::Scalar::create(context, _minDistance); + + vx_size capacity = image.cols * image.rows; + Array corners = Array::create(context, VX_TYPE_KEYPOINT, capacity); + ivx::Scalar numCorners = ivx::Scalar::create(context, 0); + + IVX_CHECK_STATUS(vxuHarrisCorners(context, ovxImage, strengthThresh, minDistance, sensivity, + gradientSize, blockSize, corners, numCorners)); + + std::vector vxKeypoints; + corners.copyTo(vxKeypoints); + + std::sort(vxKeypoints.begin(), vxKeypoints.end(), VxKeypointsComparator()); + + vx_float32 maxStrength = 0.0f; + if(vxKeypoints.size() > 0) + maxStrength = vxKeypoints[0].strength; + size_t maxKeypoints = min((size_t)_maxCorners, vxKeypoints.size()); + std::vector keypoints; + keypoints.reserve(maxKeypoints); + for(size_t i = 0; i < maxKeypoints; i++) + { + vx_keypoint_t kp = vxKeypoints[i]; + if(kp.strength < maxStrength*_qualityLevel) break; + keypoints.push_back(Point2f((float)kp.x, (float)kp.y)); + } + + Mat(keypoints).convertTo(_corners, _corners.fixedType() ? _corners.type() : CV_32F); + +#ifdef VX_VERSION_1_1 + //we should take user memory back before release + //(it's not done automatically according to standard) + ovxImage.swapHandle(); +#endif + } + catch (RuntimeError & e) + { + VX_DbgThrow(e.what()); + } + catch (WrapperError & e) + { + VX_DbgThrow(e.what()); + } + + return true; +} + +#endif + } void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, @@ -285,6 +376,10 @@ void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, return; } + // Disabled due to bad accuracy + CV_OVX_RUN(false && useHarrisDetector && _mask.empty(), + openvx_harris(image, _corners, maxCorners, qualityLevel, minDistance, blockSize, harrisK)) + if( useHarrisDetector ) cornerHarris( image, eig, blockSize, 3, harrisK ); else