1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 15:53:03 +04:00

Merge pull request #8869 from hrnr:akaze_part1

[GSOC] Speeding-up AKAZE, part #1 (#8869)

* ts: expand arguments before stringifications in CV_ENUM and CV_FLAGS

added protective macros to always force macro expansion of arguments. This allows using CV_ENUM and CV_FLAGS with macro arguments.

* feature2d: unify perf test

use the same test for all detectors/descriptors we have.

* added AKAZE tests

* features2d: extend perf tests

* add BRISK, KAZE, MSER
* run all extract tests on AKAZE keypoints, so that the test si more comparable for the speed of extraction

* feature2d: rework opencl perf tests

use the same configuration as cpu tests

* feature2d: fix descriptors allocation for AKAZE and KAZE

fix crash when descriptors are UMat

* feature2d: name enum to fix build with older gcc

* Revert "ts: expand arguments before stringifications in CV_ENUM and CV_FLAGS"

This reverts commit 19538cac1e.

This wasn't a great idea after all. There is a lot of flags implemented as #define, that we don't want to expand.

* feature2d: fix expansion problems with CV_ENUM in perf

* expand arguments before passing them to CV_ENUM. This does not need modifications of CV_ENUM.
* added include guards to `perf_feature2d.hpp`

* feature2d: fix crash in AKAZE when using KAZE descriptors

* out-of-bound access in Get_MSURF_Descriptor_64
* this happened reliably when running on provided keypoints (not computed by the same instance)

* feature2d: added regression tests for AKAZE

* test with both MLDB and KAZE keypoints

* feature2d: do not compute keypoints orientation twice

* always compute keypoints orientation, when computing keypoints
* do not recompute keypoint orientation when computing descriptors

this allows to test detection and extraction separately

* features2d: fix crash in AKAZE

* out-of-bound reads near the image edge
* same as the bug in KAZE descriptors

* feature2d: refactor invariance testing

* split detectors and descriptors tests
* rewrite to google test to simplify debugging
* add tests for AKAZE and one test for ORB

* stitching: add tests with AKAZE feature finder

* added basic stitching cpu and ocl tests
* fix bug in AKAZE wrapper for stitching pipeline causing lots of
! OPENCV warning: getUMat()/getMat() call chain possible problem.
!                 Base object is dead, while nested/derived object is still alive or processed.
!                 Please check lifetime of UMat/Mat objects!
This commit is contained in:
Jiri Horner
2017-06-21 13:33:09 +02:00
committed by Alexander Alekhin
parent 437ca0b62a
commit 5f20e802d2
21 changed files with 849 additions and 1085 deletions
+4 -3
View File
@@ -200,8 +200,7 @@ namespace cv
if (!useProvidedKeypoints)
{
impl.Feature_Detection(keypoints);
if( !descriptors.needed() )
impl.Compute_Keypoints_Orientation(keypoints);
impl.Compute_Keypoints_Orientation(keypoints);
}
if (!mask.empty())
@@ -211,8 +210,10 @@ namespace cv
if( descriptors.needed() )
{
Mat& desc = descriptors.getMatRef();
Mat desc;
impl.Compute_Descriptors(keypoints, desc);
// TODO optimize this copy
desc.copyTo(descriptors);
CV_Assert((!desc.rows || desc.cols == descriptorSize()));
CV_Assert((!desc.rows || (desc.type() == descriptorType())));
+2 -1
View File
@@ -151,8 +151,9 @@ namespace cv
if( descriptors.needed() )
{
Mat& desc = descriptors.getMatRef();
Mat desc;
impl.Feature_Description(keypoints, desc);
desc.copyTo(descriptors);
CV_Assert((!desc.rows || desc.cols == descriptorSize()));
CV_Assert((!desc.rows || (desc.type() == descriptorType())));
+28 -13
View File
@@ -549,7 +549,6 @@ public:
{
for (int i = range.start; i < range.end; i++)
{
AKAZEFeatures::Compute_Main_Orientation((*keypoints_)[i], *evolution_);
Get_MSURF_Descriptor_64((*keypoints_)[i], descriptors_->ptr<float>(i));
}
}
@@ -643,7 +642,6 @@ public:
{
for (int i = range.start; i < range.end; i++)
{
AKAZEFeatures::Compute_Main_Orientation((*keypoints_)[i], *evolution_);
Get_MLDB_Full_Descriptor((*keypoints_)[i], descriptors_->ptr<unsigned char>(i));
}
}
@@ -1055,19 +1053,28 @@ void MSURF_Descriptor_64_Invoker::Get_MSURF_Descriptor_64(const KeyPoint& kpt, f
y2 = fRound(sample_y + 0.5f);
x2 = fRound(sample_x + 0.5f);
// fix crash: indexing with out-of-bounds index, this might happen near the edges of image
// clip values so they fit into the image
const MatSize& size = evolution[level].Lx.size;
y1 = min(max(0, y1), size[0] - 1);
x1 = min(max(0, x1), size[1] - 1);
y2 = min(max(0, y2), size[0] - 1);
x2 = min(max(0, x2), size[1] - 1);
CV_DbgAssert(evolution[level].Lx.size == evolution[level].Ly.size);
fx = sample_x - x1;
fy = sample_y - y1;
res1 = *(evolution[level].Lx.ptr<float>(y1)+x1);
res2 = *(evolution[level].Lx.ptr<float>(y1)+x2);
res3 = *(evolution[level].Lx.ptr<float>(y2)+x1);
res4 = *(evolution[level].Lx.ptr<float>(y2)+x2);
res1 = *(evolution[level].Lx.ptr<float>(y1, x1));
res2 = *(evolution[level].Lx.ptr<float>(y1, x2));
res3 = *(evolution[level].Lx.ptr<float>(y2, x1));
res4 = *(evolution[level].Lx.ptr<float>(y2, x2));
rx = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
res1 = *(evolution[level].Ly.ptr<float>(y1)+x1);
res2 = *(evolution[level].Ly.ptr<float>(y1)+x2);
res3 = *(evolution[level].Ly.ptr<float>(y2)+x1);
res4 = *(evolution[level].Ly.ptr<float>(y2)+x2);
res1 = *(evolution[level].Ly.ptr<float>(y1, x1));
res2 = *(evolution[level].Ly.ptr<float>(y1, x2));
res3 = *(evolution[level].Ly.ptr<float>(y2, x1));
res4 = *(evolution[level].Ly.ptr<float>(y2, x2));
ry = (1.0f - fx)*(1.0f - fy)*res1 + fx*(1.0f - fy)*res2 + (1.0f - fx)*fy*res3 + fx*fy*res4;
// Get the x and y derivatives on the rotated axis
@@ -1228,12 +1235,20 @@ void MLDB_Full_Descriptor_Invoker::MLDB_Fill_Values(float* values, int sample_st
int y1 = fRound(sample_y);
int x1 = fRound(sample_x);
float ri = *(evolution[level].Lt.ptr<float>(y1)+x1);
// fix crash: indexing with out-of-bounds index, this might happen near the edges of image
// clip values so they fit into the image
const MatSize& size = evolution[level].Lt.size;
CV_DbgAssert(size == evolution[level].Lx.size &&
size == evolution[level].Ly.size);
y1 = min(max(0, y1), size[0] - 1);
x1 = min(max(0, x1), size[1] - 1);
float ri = *(evolution[level].Lt.ptr<float>(y1, x1));
di += ri;
if(chan > 1) {
float rx = *(evolution[level].Lx.ptr<float>(y1)+x1);
float ry = *(evolution[level].Ly.ptr<float>(y1)+x1);
float rx = *(evolution[level].Lx.ptr<float>(y1, x1));
float ry = *(evolution[level].Ly.ptr<float>(y1, x1));
if (chan == 2) {
dx += sqrtf(rx*rx + ry*ry);
}