From 137ff7eccbd48f1f3d60ca423d96c721d83599e7 Mon Sep 17 00:00:00 2001 From: Ievgen Khvedchenia Date: Sat, 5 Apr 2014 10:25:46 +0300 Subject: [PATCH] Added KAZE and AKAZE wrappers --- .../features2d/include/opencv2/features2d.hpp | 66 ++++++++ modules/features2d/src/akaze.cpp | 149 ++++++++++++++++++ modules/features2d/src/features2d_init.cpp | 20 ++- modules/features2d/src/kaze.cpp | 120 ++++++++++++++ 4 files changed, 353 insertions(+), 2 deletions(-) create mode 100644 modules/features2d/src/akaze.cpp diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index 190e8ac66..e45c17771 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -887,7 +887,73 @@ protected: PixelTestFn test_fn_; }; +/*! +KAZE implementation +*/ +class CV_EXPORTS_W KAZE : public Feature2D +{ +public: + CV_WRAP explicit KAZE(bool _extended = false); + virtual ~KAZE(); + + // returns the descriptor size in bytes + int descriptorSize() const; + // returns the descriptor type + int descriptorType() const; + // returns the default norm type + int defaultNorm() const; + + AlgorithmInfo* info() const; + + void operator()(InputArray image, InputArray mask, + std::vector& keypoints, + OutputArray descriptors, + bool useProvidedKeypoints) const; + +protected: + void detectImpl(InputArray image, std::vector& keypoints, InputArray mask) const; + void computeImpl(InputArray image, std::vector& keypoints, OutputArray descriptors) const; + + CV_PROP bool extended; +}; + +/*! +AKAZE implementation +*/ +class CV_EXPORTS_W AKAZE : public Feature2D +{ +public: + CV_WRAP explicit AKAZE(int _descriptor = 5, int _descriptor_size = 0, int _descriptor_channels = 3); + + virtual ~AKAZE(); + + // returns the descriptor size in bytes + int descriptorSize() const; + // returns the descriptor type + int descriptorType() const; + // returns the default norm type + int defaultNorm() const; + + // Compute the AKAZE features on an image + void operator()(InputArray image, InputArray mask, std::vector& keypoints) const; + + // Compute the BRISK features and descriptors on an image + void operator()(InputArray image, InputArray mask, std::vector& keypoints, + OutputArray descriptors, bool useProvidedKeypoints = false) const; + + AlgorithmInfo* info() const; + +protected: + + void computeImpl(InputArray image, std::vector& keypoints, OutputArray descriptors) const; + void detectImpl(InputArray image, std::vector& keypoints, InputArray mask = noArray()) const; + + CV_PROP int descriptor_channels; + CV_PROP int descriptor; + CV_PROP int descriptor_size; + +}; /****************************************************************************************\ * Distance * \****************************************************************************************/ diff --git a/modules/features2d/src/akaze.cpp b/modules/features2d/src/akaze.cpp new file mode 100644 index 000000000..8cba3b6d2 --- /dev/null +++ b/modules/features2d/src/akaze.cpp @@ -0,0 +1,149 @@ +#include "precomp.hpp" +#include "akaze/AKAZE.h" + +namespace cv +{ + + AKAZE::AKAZE(int _descriptor, int _descriptor_size, int _descriptor_channels) + : descriptor_channels(_descriptor_channels) + , descriptor(_descriptor) + , descriptor_size(_descriptor_size) + { + + } + + AKAZE::~AKAZE() + { + + } + + // returns the descriptor size in bytes + int AKAZE::descriptorSize() const + { + if (descriptor < MLDB_UPRIGHT) + { + return 64; + } + else + { + // We use the full length binary descriptor -> 486 bits + if (descriptor_size == 0) + { + int t = (6 + 36 + 120) * descriptor_channels; + return ceil(t / 8.); + } + else + { + // We use the random bit selection length binary descriptor + return ceil(descriptor_size / 8.); + } + } + } + + // returns the descriptor type + int AKAZE::descriptorType() const + { + if (descriptor < MLDB_UPRIGHT) + { + return CV_32FC1; + } + else + { + return CV_8UC1; + } + } + + // returns the default norm type + int AKAZE::defaultNorm() const + { + if (descriptor < MLDB_UPRIGHT) + { + return NORM_L2; + } + else + { + return NORM_HAMMING; + } + } + + + void AKAZE::operator()(InputArray image, InputArray mask, + std::vector& keypoints, + OutputArray descriptors, + bool useProvidedKeypoints) const + { + cv::Mat img = image.getMat(); + if (img.type() != CV_8UC1) + cvtColor(image, img, COLOR_BGR2GRAY); + + Mat img1_32; + img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0); + + cv::Mat& desc = descriptors.getMatRef(); + + AKAZEOptions options; + options.img_width = img.cols; + options.img_height = img.rows; + + AKAZEFeatures impl(options); + impl.Create_Nonlinear_Scale_Space(img1_32); + + if (!useProvidedKeypoints) + { + impl.Feature_Detection(keypoints); + } + + if (!mask.empty()) + { + cv::KeyPointsFilter::runByPixelsMask(keypoints, mask.getMat()); + } + + impl.Compute_Descriptors(keypoints, desc); + } + + void AKAZE::detectImpl(InputArray image, std::vector& keypoints, InputArray mask) const + { + cv::Mat img = image.getMat(); + if (img.type() != CV_8UC1) + cvtColor(image, img, COLOR_BGR2GRAY); + + Mat img1_32; + img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0); + + AKAZEOptions options; + options.img_width = img.cols; + options.img_height = img.rows; + + AKAZEFeatures impl(options); + impl.Create_Nonlinear_Scale_Space(img1_32); + impl.Feature_Detection(keypoints); + + if (!mask.empty()) + { + cv::KeyPointsFilter::runByPixelsMask(keypoints, mask.getMat()); + } + } + + void AKAZE::computeImpl(InputArray image, std::vector& keypoints, OutputArray descriptors) const + { + cv::Mat img = image.getMat(); + if (img.type() != CV_8UC1) + cvtColor(image, img, COLOR_BGR2GRAY); + + Mat img1_32; + img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0); + + cv::Mat& desc = descriptors.getMatRef(); + + AKAZEOptions options; + options.img_width = img.cols; + options.img_height = img.rows; + + AKAZEFeatures impl(options); + impl.Create_Nonlinear_Scale_Space(img1_32); + impl.Compute_Descriptors(keypoints, desc); + + CV_Assert(!desc.rows || desc.cols == descriptorSize() && "Descriptor size does not match expected"); + CV_Assert(!desc.rows || (desc.type() & descriptorType()) && "Descriptor type does not match expected"); + } +} \ No newline at end of file diff --git a/modules/features2d/src/features2d_init.cpp b/modules/features2d/src/features2d_init.cpp index 889c5b64c..e3a3b3c36 100644 --- a/modules/features2d/src/features2d_init.cpp +++ b/modules/features2d/src/features2d_init.cpp @@ -125,6 +125,20 @@ CV_INIT_ALGORITHM(GFTTDetector, "Feature2D.GFTT", /////////////////////////////////////////////////////////////////////////////////////////////////////////// +CV_INIT_ALGORITHM(KAZE, "Feature2D.KAZE", + obj.info()->addParam(obj, "extended", obj.extended)) + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +CV_INIT_ALGORITHM(AKAZE, "Feature2D.AKAZE", + obj.info()->addParam(obj, "descriptor_channels", obj.descriptor_channels); + obj.info()->addParam(obj, "descriptor", obj.descriptor); + obj.info()->addParam(obj, "descriptor_size", obj.descriptor_size)) + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + CV_INIT_ALGORITHM(SimpleBlobDetector, "Feature2D.SimpleBlob", obj.info()->addParam(obj, "thresholdStep", obj.params.thresholdStep); obj.info()->addParam(obj, "minThreshold", obj.params.minThreshold); @@ -202,11 +216,13 @@ bool cv::initModule_features2d(void) all &= !FREAK_info_auto.name().empty(); all &= !ORB_info_auto.name().empty(); all &= !GFTTDetector_info_auto.name().empty(); - all &= !HarrisDetector_info_auto.name().empty(); + all &= !KAZE_info_auto.name().empty(); + all &= !AKAZE_info_auto.name().empty(); + all &= !HarrisDetector_info_auto.name().empty(); all &= !DenseFeatureDetector_info_auto.name().empty(); all &= !GridAdaptedFeatureDetector_info_auto.name().empty(); all &= !BFMatcher_info_auto.name().empty(); all &= !FlannBasedMatcher_info_auto.name().empty(); return all; -} +} \ No newline at end of file diff --git a/modules/features2d/src/kaze.cpp b/modules/features2d/src/kaze.cpp index e69de29bb..1944f1e4e 100644 --- a/modules/features2d/src/kaze.cpp +++ b/modules/features2d/src/kaze.cpp @@ -0,0 +1,120 @@ +#include "precomp.hpp" +#include "kaze/KAZE.h" + +namespace cv +{ + KAZE::KAZE(bool _extended /* = false */) + : extended(_extended) + { + } + + KAZE::~KAZE() + { + + } + + // returns the descriptor size in bytes + int KAZE::descriptorSize() const + { + return extended ? 128 : 64; + } + + // returns the descriptor type + int KAZE::descriptorType() const + { + return CV_32F; + } + + // returns the default norm type + int KAZE::defaultNorm() const + { + return NORM_L2; + } + + + void KAZE::operator()(InputArray image, InputArray mask, + std::vector& keypoints, + OutputArray descriptors, + bool useProvidedKeypoints) const + { + cv::Mat img = image.getMat(); + if (img.type() != CV_8UC1) + cvtColor(image, img, COLOR_BGR2GRAY); + + Mat img1_32; + img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0); + + cv::Mat& desc = descriptors.getMatRef(); + + KAZEOptions options; + options.img_width = img.cols; + options.img_height = img.rows; + options.extended = extended; + + KAZEFeatures impl(options); + impl.Create_Nonlinear_Scale_Space(img1_32); + + if (!useProvidedKeypoints) + { + impl.Feature_Detection(keypoints); + } + + if (!mask.empty()) + { + cv::KeyPointsFilter::runByPixelsMask(keypoints, mask.getMat()); + } + + impl.Feature_Description(keypoints, desc); + + CV_Assert(!desc.rows || desc.cols == descriptorSize() && "Descriptor size does not match expected"); + CV_Assert(!desc.rows || (desc.type() & descriptorType()) && "Descriptor type does not match expected"); + } + + void KAZE::detectImpl(InputArray image, std::vector& keypoints, InputArray mask) const + { + Mat img = image.getMat(); + if (img.type() != CV_8UC1) + cvtColor(image, img, COLOR_BGR2GRAY); + + Mat img1_32; + img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0); + + KAZEOptions options; + options.img_width = img.cols; + options.img_height = img.rows; + options.extended = extended; + + KAZEFeatures impl(options); + impl.Create_Nonlinear_Scale_Space(img1_32); + impl.Feature_Detection(keypoints); + + if (!mask.empty()) + { + cv::KeyPointsFilter::runByPixelsMask(keypoints, mask.getMat()); + } + } + + void KAZE::computeImpl(InputArray image, std::vector& keypoints, OutputArray descriptors) const + { + cv::Mat img = image.getMat(); + if (img.type() != CV_8UC1) + cvtColor(image, img, COLOR_BGR2GRAY); + + Mat img1_32; + img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0); + + cv::Mat& desc = descriptors.getMatRef(); + + KAZEOptions options; + options.img_width = img.cols; + options.img_height = img.rows; + options.extended = extended; + + KAZEFeatures impl(options); + impl.Create_Nonlinear_Scale_Space(img1_32); + impl.Feature_Description(keypoints, desc); + + CV_Assert(!desc.rows || desc.cols == descriptorSize() && "Descriptor size does not match expected"); + CV_Assert(!desc.rows || (desc.type() & descriptorType()) && "Descriptor type does not match expected"); + } +} \ No newline at end of file