OCL: included ORB featured detector/descriptor extractor.

parent b29835a8
......@@ -647,3 +647,138 @@ Returns block descriptors computed for the whole image.
* **DESCR_FORMAT_COL_BY_COL** - Column-major order.
The function is mainly used to learn the classifier.
ocl::ORB_OCL
--------------
.. ocv:class:: ocl::ORB_OCL
Class for extracting ORB features and descriptors from an image. ::
class ORB_OCL
{
public:
enum
{
X_ROW = 0,
Y_ROW,
RESPONSE_ROW,
ANGLE_ROW,
OCTAVE_ROW,
SIZE_ROW,
ROWS_COUNT
};
enum
{
DEFAULT_FAST_THRESHOLD = 20
};
explicit ORB_OCL(int nFeatures = 500, float scaleFactor = 1.2f,
int nLevels = 8, int edgeThreshold = 31,
int firstLevel = 0, int WTA_K = 2,
int scoreType = 0, int patchSize = 31);
void operator()(const oclMat& image, const oclMat& mask,
std::vector<KeyPoint>& keypoints);
void operator()(const oclMat& image, const oclMat& mask, oclMat& keypoints);
void operator()(const oclMat& image, const oclMat& mask,
std::vector<KeyPoint>& keypoints, oclMat& descriptors);
void operator()(const oclMat& image, const oclMat& mask,
oclMat& keypoints, oclMat& descriptors);
void downloadKeyPoints(oclMat& d_keypoints, std::vector<KeyPoint>& keypoints);
void convertKeyPoints(Mat& d_keypoints, std::vector<KeyPoint>& keypoints);
int descriptorSize() const;
int descriptorType() const;
int defaultNorm() const;
void setFastParams(int threshold, bool nonmaxSupression = true);
void release();
bool blurForDescriptor;
};
The class implements ORB feature detection and description algorithm.
ocl::ORB_OCL::ORB_OCL
------------------------
Constructor.
.. ocv:function:: ocl::ORB_OCL::ORB_OCL(int nFeatures = 500, float scaleFactor = 1.2f, int nLevels = 8, int edgeThreshold = 31, int firstLevel = 0, int WTA_K = 2, int scoreType = 0, int patchSize = 31)
:param nfeatures: The maximum number of features to retain.
:param scaleFactor: Pyramid decimation ratio, greater than 1. ``scaleFactor==2`` means the classical pyramid, where each next level has 4x less pixels than the previous, but such a big scale factor will degrade feature matching scores dramatically. On the other hand, too close to 1 scale factor will mean that to cover certain scale range you will need more pyramid levels and so the speed will suffer.
:param nlevels: The number of pyramid levels. The smallest level will have linear size equal to ``input_image_linear_size/pow(scaleFactor, nlevels)``.
:param edgeThreshold: This is size of the border where the features are not detected. It should roughly match the ``patchSize`` parameter.
:param firstLevel: It should be 0 in the current implementation.
:param WTA_K: The number of points that produce each element of the oriented BRIEF descriptor. The default value 2 means the BRIEF where we take a random point pair and compare their brightnesses, so we get 0/1 response. Other possible values are 3 and 4. For example, 3 means that we take 3 random points (of course, those point coordinates are random, but they are generated from the pre-defined seed, so each element of BRIEF descriptor is computed deterministically from the pixel rectangle), find point of maximum brightness and output index of the winner (0, 1 or 2). Such output will occupy 2 bits, and therefore it will need a special variant of Hamming distance, denoted as ``NORM_HAMMING2`` (2 bits per bin). When ``WTA_K=4``, we take 4 random points to compute each bin (that will also occupy 2 bits with possible values 0, 1, 2 or 3).
:param scoreType: The default HARRIS_SCORE means that Harris algorithm is used to rank features (the score is written to ``KeyPoint::score`` and is used to retain best ``nfeatures`` features); FAST_SCORE is alternative value of the parameter that produces slightly less stable keypoints, but it is a little faster to compute.
:param patchSize: size of the patch used by the oriented BRIEF descriptor. Of course, on smaller pyramid layers the perceived image area covered by a feature will be larger.
ocl::ORB_OCL::operator()
--------------------------
Detects keypoints and computes descriptors for them.
.. ocv:function:: void ocl::ORB_OCL::operator()(const oclMat& image, const oclMat& mask, std::vector<KeyPoint>& keypoints)
.. ocv:function:: void ocl::ORB_OCL::operator()(const oclMat& image, const oclMat& mask, oclMat& keypoints)
.. ocv:function:: void ocl::ORB_OCL::operator()(const oclMat& image, const oclMat& mask, std::vector<KeyPoint>& keypoints, oclMat& descriptors)
.. ocv:function:: void ocl::ORB_OCL::operator()(const oclMat& image, const oclMat& mask, oclMat& keypoints, oclMat& descriptors)
:param image: Input 8-bit grayscale image.
:param mask: Optional input mask that marks the regions where we should detect features.
:param keypoints: The input/output vector of keypoints. Can be stored both in host and device memory. For device memory:
* ``X_ROW`` contains the horizontal coordinate of the i'th feature.
* ``Y_ROW`` contains the vertical coordinate of the i'th feature.
* ``RESPONSE_ROW`` contains the response of the i'th feature.
* ``ANGLE_ROW`` contains the orientation of the i'th feature.
* ``RESPONSE_ROW`` contains the octave of the i'th feature.
* ``ANGLE_ROW`` contains the size of the i'th feature.
:param descriptors: Computed descriptors. if ``blurForDescriptor`` is true, image will be blurred before descriptors calculation.
ocl::ORB_OCL::downloadKeyPoints
---------------------------------
Download keypoints from device to host memory.
.. ocv:function:: static void ocl::ORB_OCL::downloadKeyPoints( const oclMat& d_keypoints, std::vector<KeyPoint>& keypoints )
ocl::ORB_OCL::convertKeyPoints
--------------------------------
Converts keypoints from OCL representation to vector of ``KeyPoint``.
.. ocv:function:: static void ocl::ORB_OCL::convertKeyPoints( const Mat& d_keypoints, std::vector<KeyPoint>& keypoints )
ocl::ORB_OCL::release
-----------------------
Releases inner buffer memory.
.. ocv:function:: void ocl::ORB_OCL::release()
......@@ -1513,6 +1513,110 @@ namespace cv
int nonmaxSupressionOCL(oclMat& keypoints);
};
////////////////////////////////// ORB Descriptor Extractor //////////////////////////////////
class CV_EXPORTS ORB_OCL
{
public:
enum
{
X_ROW = 0,
Y_ROW,
RESPONSE_ROW,
ANGLE_ROW,
OCTAVE_ROW,
SIZE_ROW,
ROWS_COUNT
};
enum
{
DEFAULT_FAST_THRESHOLD = 20
};
//! Constructor
explicit ORB_OCL(int nFeatures = 500, float scaleFactor = 1.2f, int nLevels = 8, int edgeThreshold = 31,
int firstLevel = 0, int WTA_K = 2, int scoreType = 0, int patchSize = 31);
//! Compute the ORB features on an image
//! image - the image to compute the features (supports only CV_8UC1 images)
//! mask - the mask to apply
//! keypoints - the resulting keypoints
void operator ()(const oclMat& image, const oclMat& mask, std::vector<KeyPoint>& keypoints);
void operator ()(const oclMat& image, const oclMat& mask, oclMat& keypoints);
//! Compute the ORB features and descriptors on an image
//! image - the image to compute the features (supports only CV_8UC1 images)
//! mask - the mask to apply
//! keypoints - the resulting keypoints
//! descriptors - descriptors array
void operator ()(const oclMat& image, const oclMat& mask, std::vector<KeyPoint>& keypoints, oclMat& descriptors);
void operator ()(const oclMat& image, const oclMat& mask, oclMat& keypoints, oclMat& descriptors);
//! download keypoints from device to host memory
static void downloadKeyPoints(const oclMat& d_keypoints, std::vector<KeyPoint>& keypoints);
//! convert keypoints to KeyPoint vector
static void convertKeyPoints(const Mat& d_keypoints, std::vector<KeyPoint>& keypoints);
//! returns the descriptor size in bytes
inline int descriptorSize() const { return kBytes; }
inline int descriptorType() const { return CV_8U; }
inline int defaultNorm() const { return NORM_HAMMING; }
inline void setFastParams(int threshold, bool nonmaxSupression = true)
{
fastDetector_.threshold = threshold;
fastDetector_.nonmaxSupression = nonmaxSupression;
}
//! release temporary buffer's memory
void release();
//! if true, image will be blurred before descriptors calculation
bool blurForDescriptor;
private:
enum { kBytes = 32 };
void buildScalePyramids(const oclMat& image, const oclMat& mask);
void computeKeyPointsPyramid();
void computeDescriptors(oclMat& descriptors);
void mergeKeyPoints(oclMat& keypoints);
int nFeatures_;
float scaleFactor_;
int nLevels_;
int edgeThreshold_;
int firstLevel_;
int WTA_K_;
int scoreType_;
int patchSize_;
// The number of desired features per scale
std::vector<size_t> n_features_per_level_;
// Points to compute BRIEF descriptors from
oclMat pattern_;
std::vector<oclMat> imagePyr_;
std::vector<oclMat> maskPyr_;
oclMat buf_;
std::vector<oclMat> keyPointsPyr_;
std::vector<int> keyPointsCount_;
FAST_OCL fastDetector_;
Ptr<ocl::FilterEngine_GPU> blurFilter;
oclMat d_keypoints_;
oclMat uMax_;
};
/////////////////////////////// PyrLKOpticalFlow /////////////////////////////////////
class CV_EXPORTS PyrLKOpticalFlow
......
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
// Authors:
// * Peter Andreas Entschev, peter@entschev.com
//
//M*/
#include "perf_precomp.hpp"
using namespace perf;
/////////////////// ORB ///////////////////
typedef std::tr1::tuple<std::string, int> Image_NFeatures_t;
typedef perf::TestBaseWithParam<Image_NFeatures_t> Image_NFeatures;
PERF_TEST_P(Image_NFeatures, ORB,
testing::Combine(testing::Values<string>("gpu/perf/aloe.png"),
testing::Values(4000)))
{
declare.time(300.0);
const Image_NFeatures_t params = GetParam();
const std::string imgFile = std::tr1::get<0>(params);
const int nFeatures = std::tr1::get<1>(params);
const cv::Mat img = imread(getDataPath(imgFile), cv::IMREAD_GRAYSCALE);
ASSERT_FALSE(img.empty());
if (RUN_OCL_IMPL)
{
cv::ocl::ORB_OCL d_orb(nFeatures);
const cv::ocl::oclMat d_img(img);
cv::ocl::oclMat d_keypoints, d_descriptors;
TEST_CYCLE() d_orb(d_img, cv::ocl::oclMat(), d_keypoints, d_descriptors);
std::vector<cv::KeyPoint> ocl_keypoints;
d_orb.downloadKeyPoints(d_keypoints, ocl_keypoints);
cv::Mat ocl_descriptors(d_descriptors);
ocl_keypoints.resize(10);
ocl_descriptors = ocl_descriptors.rowRange(0, 10);
sortKeyPoints(ocl_keypoints, ocl_descriptors);
SANITY_CHECK_KEYPOINTS(ocl_keypoints, 1e-4);
SANITY_CHECK(ocl_descriptors);
}
else if (RUN_PLAIN_IMPL)
{
cv::ORB orb(nFeatures);
std::vector<cv::KeyPoint> cpu_keypoints;
cv::Mat cpu_descriptors;
TEST_CYCLE() orb(img, cv::noArray(), cpu_keypoints, cpu_descriptors);
SANITY_CHECK_KEYPOINTS(cpu_keypoints);
SANITY_CHECK(cpu_descriptors);
}
else
OCL_PERF_ELSE;
}
This diff is collapsed.
This diff is collapsed.
......@@ -72,6 +72,7 @@
#include "opencv2/imgproc.hpp"
#include "opencv2/objdetect/objdetect_c.h"
#include "opencv2/ocl.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/core/private.hpp"
......
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
// Authors:
// * Peter Andreas Entschev, peter@entschev.com
//
//M*/
#include "test_precomp.hpp"
#ifdef HAVE_OPENCL
////////////////////////////////////////////////////////
// ORB
namespace
{
IMPLEMENT_PARAM_CLASS(ORB_FeaturesCount, int)
IMPLEMENT_PARAM_CLASS(ORB_ScaleFactor, float)
IMPLEMENT_PARAM_CLASS(ORB_LevelsCount, int)
IMPLEMENT_PARAM_CLASS(ORB_EdgeThreshold, int)
IMPLEMENT_PARAM_CLASS(ORB_firstLevel, int)
IMPLEMENT_PARAM_CLASS(ORB_WTA_K, int)
IMPLEMENT_PARAM_CLASS(ORB_PatchSize, int)
IMPLEMENT_PARAM_CLASS(ORB_BlurForDescriptor, bool)
}
CV_ENUM(ORB_ScoreType, ORB::HARRIS_SCORE, ORB::FAST_SCORE)
PARAM_TEST_CASE(ORB, ORB_FeaturesCount, ORB_ScaleFactor, ORB_LevelsCount, ORB_EdgeThreshold,
ORB_firstLevel, ORB_WTA_K, ORB_ScoreType, ORB_PatchSize, ORB_BlurForDescriptor)
{
int nFeatures;
float scaleFactor;
int nLevels;
int edgeThreshold;
int firstLevel;
int WTA_K;
int scoreType;
int patchSize;
bool blurForDescriptor;
virtual void SetUp()
{
nFeatures = GET_PARAM(0);
scaleFactor = GET_PARAM(1);
nLevels = GET_PARAM(2);
edgeThreshold = GET_PARAM(3);
firstLevel = GET_PARAM(4);
WTA_K = GET_PARAM(5);
scoreType = GET_PARAM(6);
patchSize = GET_PARAM(7);
blurForDescriptor = GET_PARAM(8);
}
};
OCL_TEST_P(ORB, Accuracy)
{
cv::Mat image = readImage("gpu/perf/aloe.png", cv::IMREAD_GRAYSCALE);
ASSERT_FALSE(image.empty());
cv::Mat mask(image.size(), CV_8UC1, cv::Scalar::all(1));
mask(cv::Range(0, image.rows / 2), cv::Range(0, image.cols / 2)).setTo(cv::Scalar::all(0));
cv::ocl::oclMat ocl_image = cv::ocl::oclMat(image);
cv::ocl::oclMat ocl_mask = cv::ocl::oclMat(mask);
cv::ocl::ORB_OCL orb(nFeatures, scaleFactor, nLevels, edgeThreshold, firstLevel, WTA_K, scoreType, patchSize);
orb.blurForDescriptor = blurForDescriptor;
std::vector<cv::KeyPoint> keypoints;
cv::ocl::oclMat descriptors;
orb(ocl_image, ocl_mask, keypoints, descriptors);
cv::ORB orb_gold(nFeatures, scaleFactor, nLevels, edgeThreshold, firstLevel, WTA_K, scoreType, patchSize);
std::vector<cv::KeyPoint> keypoints_gold;
cv::Mat descriptors_gold;
orb_gold(image, mask, keypoints_gold, descriptors_gold);
cv::BFMatcher matcher(cv::NORM_HAMMING);
std::vector<cv::DMatch> matches;
matcher.match(descriptors_gold, cv::Mat(descriptors), matches);
int matchedCount = getMatchedPointsCount(keypoints_gold, keypoints, matches);
double matchedRatio = static_cast<double>(matchedCount) / keypoints.size();
EXPECT_GT(matchedRatio, 0.35);
}
INSTANTIATE_TEST_CASE_P(OCL_Features2D, ORB, testing::Combine(
testing::Values(ORB_FeaturesCount(1000)),
testing::Values(ORB_ScaleFactor(1.2f)),
testing::Values(ORB_LevelsCount(4), ORB_LevelsCount(8)),
testing::Values(ORB_EdgeThreshold(31)),
testing::Values(ORB_firstLevel(0), ORB_firstLevel(2)),
testing::Values(ORB_WTA_K(2), ORB_WTA_K(3), ORB_WTA_K(4)),
testing::Values(ORB_ScoreType(cv::ORB::HARRIS_SCORE)),
testing::Values(ORB_PatchSize(31), ORB_PatchSize(29)),
testing::Values(ORB_BlurForDescriptor(false), ORB_BlurForDescriptor(true))));
#endif
......@@ -325,4 +325,42 @@ testing::AssertionResult assertKeyPointsEquals(const char* gold_expr, const char
return ::testing::AssertionSuccess();
}
int getMatchedPointsCount(std::vector<cv::KeyPoint>& gold, std::vector<cv::KeyPoint>& actual)
{
std::sort(actual.begin(), actual.end(), KeyPointLess());
std::sort(gold.begin(), gold.end(), KeyPointLess());
int validCount = 0;
size_t sz = std::min(gold.size(), actual.size());
for (size_t i = 0; i < sz; ++i)
{
const cv::KeyPoint& p1 = gold[i];
const cv::KeyPoint& p2 = actual[i];
if (keyPointsEquals(p1, p2))
++validCount;
}
return validCount;
}
int getMatchedPointsCount(const std::vector<cv::KeyPoint>& keypoints1, const std::vector<cv::KeyPoint>& keypoints2, const std::vector<cv::DMatch>& matches)
{
int validCount = 0;
for (size_t i = 0; i < matches.size(); ++i)
{
const cv::DMatch& m = matches[i];
const cv::KeyPoint& p1 = keypoints1[m.queryIdx];
const cv::KeyPoint& p2 = keypoints2[m.trainIdx];
if (keyPointsEquals(p1, p2))
++validCount;
}
return validCount;
}
} // namespace cvtest
......@@ -56,6 +56,8 @@ namespace cvtest {
testing::AssertionResult assertKeyPointsEquals(const char* gold_expr, const char* actual_expr, std::vector<cv::KeyPoint>& gold, std::vector<cv::KeyPoint>& actual);
#define ASSERT_KEYPOINTS_EQ(gold, actual) EXPECT_PRED_FORMAT2(assertKeyPointsEquals, gold, actual)
CV_EXPORTS int getMatchedPointsCount(std::vector<cv::KeyPoint>& gold, std::vector<cv::KeyPoint>& actual);
CV_EXPORTS int getMatchedPointsCount(const std::vector<cv::KeyPoint>& keypoints1, const std::vector<cv::KeyPoint>& keypoints2, const std::vector<cv::DMatch>& matches);
void showDiff(const Mat& src, const Mat& gold, const Mat& actual, double eps, bool alwaysShow = false);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment