feat: 切换后端至PaddleOCR-NCNN,切换工程为CMake
1.项目后端整体迁移至PaddleOCR-NCNN算法,已通过基本的兼容性测试 2.工程改为使用CMake组织,后续为了更好地兼容第三方库,不再提供QMake工程 3.重整权利声明文件,重整代码工程,确保最小化侵权风险 Log: 切换后端至PaddleOCR-NCNN,切换工程为CMake Change-Id: I4d5d2c5d37505a4a24b389b1a4c5d12f17bfa38c
This commit is contained in:
213
3rdparty/opencv-4.5.4/modules/features2d/test/ocl/test_brute_force_matcher.cpp
vendored
Normal file
213
3rdparty/opencv-4.5.4/modules/features2d/test/ocl/test_brute_force_matcher.cpp
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
// Jia Haipeng, jiahaipeng95@gmail.com
|
||||
// Zero Lin, Zero.Lin@amd.com
|
||||
// Zhang Ying, zhangying913@gmail.com
|
||||
// Yao Wang, bitwangyaoyao@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
#include "cvconfig.h"
|
||||
#include "opencv2/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
PARAM_TEST_CASE(BruteForceMatcher, int, int)
|
||||
{
|
||||
int distType;
|
||||
int dim;
|
||||
|
||||
int queryDescCount;
|
||||
int countFactor;
|
||||
|
||||
Mat query, train;
|
||||
UMat uquery, utrain;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
distType = GET_PARAM(0);
|
||||
dim = GET_PARAM(1);
|
||||
|
||||
queryDescCount = 300; // must be even number because we split train data in some cases in two
|
||||
countFactor = 4; // do not change it
|
||||
|
||||
cv::Mat queryBuf, trainBuf;
|
||||
|
||||
// Generate query descriptors randomly.
|
||||
// Descriptor vector elements are integer values.
|
||||
queryBuf.create(queryDescCount, dim, CV_32SC1);
|
||||
rng.fill(queryBuf, cv::RNG::UNIFORM, cv::Scalar::all(0), cv::Scalar::all(3));
|
||||
queryBuf.convertTo(queryBuf, CV_32FC1);
|
||||
|
||||
// Generate train descriptors as follows:
|
||||
// copy each query descriptor to train set countFactor times
|
||||
// and perturb some one element of the copied descriptors in
|
||||
// in ascending order. General boundaries of the perturbation
|
||||
// are (0.f, 1.f).
|
||||
trainBuf.create(queryDescCount * countFactor, dim, CV_32FC1);
|
||||
float step = 1.f / countFactor;
|
||||
for (int qIdx = 0; qIdx < queryDescCount; qIdx++)
|
||||
{
|
||||
cv::Mat queryDescriptor = queryBuf.row(qIdx);
|
||||
for (int c = 0; c < countFactor; c++)
|
||||
{
|
||||
int tIdx = qIdx * countFactor + c;
|
||||
cv::Mat trainDescriptor = trainBuf.row(tIdx);
|
||||
queryDescriptor.copyTo(trainDescriptor);
|
||||
int elem = rng(dim);
|
||||
float diff = rng.uniform(step * c, step * (c + 1));
|
||||
trainDescriptor.at<float>(0, elem) += diff;
|
||||
}
|
||||
}
|
||||
|
||||
queryBuf.convertTo(query, CV_32F);
|
||||
trainBuf.convertTo(train, CV_32F);
|
||||
query.copyTo(uquery);
|
||||
train.copyTo(utrain);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __ANDROID__
|
||||
OCL_TEST_P(BruteForceMatcher, DISABLED_Match_Single)
|
||||
#else
|
||||
OCL_TEST_P(BruteForceMatcher, Match_Single)
|
||||
#endif
|
||||
{
|
||||
BFMatcher matcher(distType);
|
||||
|
||||
std::vector<cv::DMatch> matches;
|
||||
matcher.match(uquery, utrain, matches);
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(queryDescCount), matches.size());
|
||||
|
||||
int badCount = 0;
|
||||
for (size_t i = 0; i < matches.size(); i++)
|
||||
{
|
||||
cv::DMatch match = matches[i];
|
||||
if ((match.queryIdx != (int)i) || (match.trainIdx != (int)i * countFactor) || (match.imgIdx != 0))
|
||||
badCount++;
|
||||
}
|
||||
|
||||
ASSERT_EQ(0, badCount);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
OCL_TEST_P(BruteForceMatcher, DISABLED_KnnMatch_2_Single)
|
||||
#else
|
||||
OCL_TEST_P(BruteForceMatcher, KnnMatch_2_Single)
|
||||
#endif
|
||||
{
|
||||
const int knn = 2;
|
||||
|
||||
BFMatcher matcher(distType);
|
||||
|
||||
std::vector< std::vector<cv::DMatch> > matches;
|
||||
matcher.knnMatch(uquery, utrain, matches, knn);
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(queryDescCount), matches.size());
|
||||
|
||||
int badCount = 0;
|
||||
for (size_t i = 0; i < matches.size(); i++)
|
||||
{
|
||||
if ((int)matches[i].size() != knn)
|
||||
badCount++;
|
||||
else
|
||||
{
|
||||
int localBadCount = 0;
|
||||
for (int k = 0; k < knn; k++)
|
||||
{
|
||||
cv::DMatch match = matches[i][k];
|
||||
if ((match.queryIdx != (int)i) || (match.trainIdx != (int)i * countFactor + k) || (match.imgIdx != 0))
|
||||
localBadCount++;
|
||||
}
|
||||
badCount += localBadCount > 0 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_EQ(0, badCount);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
OCL_TEST_P(BruteForceMatcher, DISABLED_RadiusMatch_Single)
|
||||
#else
|
||||
OCL_TEST_P(BruteForceMatcher, RadiusMatch_Single)
|
||||
#endif
|
||||
{
|
||||
float radius = 1.f / countFactor;
|
||||
|
||||
BFMatcher matcher(distType);
|
||||
|
||||
std::vector< std::vector<cv::DMatch> > matches;
|
||||
matcher.radiusMatch(uquery, utrain, matches, radius);
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(queryDescCount), matches.size());
|
||||
|
||||
int badCount = 0;
|
||||
for (size_t i = 0; i < matches.size(); i++)
|
||||
{
|
||||
if ((int)matches[i].size() != 1)
|
||||
{
|
||||
badCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::DMatch match = matches[i][0];
|
||||
if ((match.queryIdx != (int)i) || (match.trainIdx != (int)i * countFactor) || (match.imgIdx != 0))
|
||||
badCount++;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_EQ(0, badCount);
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Matcher, BruteForceMatcher, Combine( Values((int)NORM_L1, (int)NORM_L2),
|
||||
Values(57, 64, 83, 128, 179, 256, 304) ) );
|
||||
|
||||
}//ocl
|
||||
}//cvtest
|
||||
|
||||
#endif //HAVE_OPENCL
|
72
3rdparty/opencv-4.5.4/modules/features2d/test/ocl/test_feature2d.cpp
vendored
Normal file
72
3rdparty/opencv-4.5.4/modules/features2d/test/ocl/test_feature2d.cpp
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
// 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"
|
||||
#include "cvconfig.h"
|
||||
#include "opencv2/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace opencv_test {
|
||||
namespace ocl {
|
||||
|
||||
#define TEST_IMAGES testing::Values(\
|
||||
"detectors_descriptors_evaluation/images_datasets/leuven/img1.png",\
|
||||
"../stitching/a3.png", \
|
||||
"../stitching/s2.jpg")
|
||||
|
||||
PARAM_TEST_CASE(Feature2DFixture, Ptr<Feature2D>, std::string)
|
||||
{
|
||||
std::string filename;
|
||||
Mat image, descriptors;
|
||||
vector<KeyPoint> keypoints;
|
||||
UMat uimage, udescriptors;
|
||||
vector<KeyPoint> ukeypoints;
|
||||
Ptr<Feature2D> feature;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
feature = GET_PARAM(0);
|
||||
filename = GET_PARAM(1);
|
||||
|
||||
image = readImage(filename);
|
||||
|
||||
ASSERT_FALSE(image.empty());
|
||||
|
||||
image.copyTo(uimage);
|
||||
|
||||
OCL_OFF(feature->detect(image, keypoints));
|
||||
OCL_ON(feature->detect(uimage, ukeypoints));
|
||||
// note: we use keypoints from CPU for GPU too, to test descriptors separately
|
||||
OCL_OFF(feature->compute(image, keypoints, descriptors));
|
||||
OCL_ON(feature->compute(uimage, keypoints, udescriptors));
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(Feature2DFixture, KeypointsSame)
|
||||
{
|
||||
EXPECT_EQ(keypoints.size(), ukeypoints.size());
|
||||
|
||||
for (size_t i = 0; i < keypoints.size(); ++i)
|
||||
{
|
||||
EXPECT_GE(KeyPoint::overlap(keypoints[i], ukeypoints[i]), 0.95);
|
||||
EXPECT_NEAR(keypoints[i].angle, ukeypoints[i].angle, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(Feature2DFixture, DescriptorsSame)
|
||||
{
|
||||
EXPECT_MAT_NEAR(descriptors, udescriptors, 0.001);
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(AKAZE, Feature2DFixture,
|
||||
testing::Combine(testing::Values(AKAZE::create()), TEST_IMAGES));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, Feature2DFixture,
|
||||
testing::Combine(testing::Values(AKAZE::create(AKAZE::DESCRIPTOR_KAZE)), TEST_IMAGES));
|
||||
|
||||
}//ocl
|
||||
}//cvtest
|
||||
|
||||
#endif //HAVE_OPENCL
|
185
3rdparty/opencv-4.5.4/modules/features2d/test/test_affine_feature.cpp
vendored
Normal file
185
3rdparty/opencv-4.5.4/modules/features2d/test/test_affine_feature.cpp
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
// 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"
|
||||
|
||||
// #define GENERATE_DATA // generate data in debug mode
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
#ifndef GENERATE_DATA
|
||||
static bool isSimilarKeypoints( const KeyPoint& p1, const KeyPoint& p2 )
|
||||
{
|
||||
const float maxPtDif = 1.f;
|
||||
const float maxSizeDif = 1.f;
|
||||
const float maxAngleDif = 2.f;
|
||||
const float maxResponseDif = 0.1f;
|
||||
|
||||
float dist = (float)cv::norm( p1.pt - p2.pt );
|
||||
return (dist < maxPtDif &&
|
||||
fabs(p1.size - p2.size) < maxSizeDif &&
|
||||
abs(p1.angle - p2.angle) < maxAngleDif &&
|
||||
abs(p1.response - p2.response) < maxResponseDif &&
|
||||
(p1.octave & 0xffff) == (p2.octave & 0xffff) // do not care about sublayers and class_id
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(Features2d_AFFINE_FEATURE, regression)
|
||||
{
|
||||
Mat image = imread(cvtest::findDataFile("features2d/tsukuba.png"));
|
||||
string xml = cvtest::TS::ptr()->get_data_path() + "asift/regression_cpp.xml.gz";
|
||||
ASSERT_FALSE(image.empty());
|
||||
|
||||
Mat gray;
|
||||
cvtColor(image, gray, COLOR_BGR2GRAY);
|
||||
|
||||
// Default ASIFT generates too large descriptors. This test uses small maxTilt to suppress the size of testdata.
|
||||
Ptr<AffineFeature> ext = AffineFeature::create(SIFT::create(), 2, 0, 1.4142135623730951f, 144.0f);
|
||||
Mat mpt, msize, mangle, mresponse, moctave, mclass_id;
|
||||
#ifdef GENERATE_DATA
|
||||
// calculate
|
||||
vector<KeyPoint> calcKeypoints;
|
||||
Mat calcDescriptors;
|
||||
ext->detectAndCompute(gray, Mat(), calcKeypoints, calcDescriptors, false);
|
||||
|
||||
// create keypoints XML
|
||||
FileStorage fs(xml, FileStorage::WRITE);
|
||||
ASSERT_TRUE(fs.isOpened()) << xml;
|
||||
std::cout << "Creating keypoints XML..." << std::endl;
|
||||
|
||||
mpt = Mat(calcKeypoints.size(), 2, CV_32F);
|
||||
msize = Mat(calcKeypoints.size(), 1, CV_32F);
|
||||
mangle = Mat(calcKeypoints.size(), 1, CV_32F);
|
||||
mresponse = Mat(calcKeypoints.size(), 1, CV_32F);
|
||||
moctave = Mat(calcKeypoints.size(), 1, CV_32S);
|
||||
mclass_id = Mat(calcKeypoints.size(), 1, CV_32S);
|
||||
|
||||
for( size_t i = 0; i < calcKeypoints.size(); i++ )
|
||||
{
|
||||
const KeyPoint& key = calcKeypoints[i];
|
||||
mpt.at<float>(i, 0) = key.pt.x;
|
||||
mpt.at<float>(i, 1) = key.pt.y;
|
||||
msize.at<float>(i, 0) = key.size;
|
||||
mangle.at<float>(i, 0) = key.angle;
|
||||
mresponse.at<float>(i, 0) = key.response;
|
||||
moctave.at<int>(i, 0) = key.octave;
|
||||
mclass_id.at<int>(i, 0) = key.class_id;
|
||||
}
|
||||
|
||||
fs << "keypoints_pt" << mpt;
|
||||
fs << "keypoints_size" << msize;
|
||||
fs << "keypoints_angle" << mangle;
|
||||
fs << "keypoints_response" << mresponse;
|
||||
fs << "keypoints_octave" << moctave;
|
||||
fs << "keypoints_class_id" << mclass_id;
|
||||
|
||||
// create descriptor XML
|
||||
fs << "descriptors" << calcDescriptors;
|
||||
fs.release();
|
||||
#else
|
||||
const float badCountsRatio = 0.01f;
|
||||
const float badDescriptorDist = 1.0f;
|
||||
const float maxBadKeypointsRatio = 0.15f;
|
||||
const float maxBadDescriptorRatio = 0.15f;
|
||||
|
||||
// read keypoints
|
||||
vector<KeyPoint> validKeypoints;
|
||||
Mat validDescriptors;
|
||||
FileStorage fs(xml, FileStorage::READ);
|
||||
ASSERT_TRUE(fs.isOpened()) << xml;
|
||||
|
||||
fs["keypoints_pt"] >> mpt;
|
||||
ASSERT_EQ(mpt.type(), CV_32F);
|
||||
fs["keypoints_size"] >> msize;
|
||||
ASSERT_EQ(msize.type(), CV_32F);
|
||||
fs["keypoints_angle"] >> mangle;
|
||||
ASSERT_EQ(mangle.type(), CV_32F);
|
||||
fs["keypoints_response"] >> mresponse;
|
||||
ASSERT_EQ(mresponse.type(), CV_32F);
|
||||
fs["keypoints_octave"] >> moctave;
|
||||
ASSERT_EQ(moctave.type(), CV_32S);
|
||||
fs["keypoints_class_id"] >> mclass_id;
|
||||
ASSERT_EQ(mclass_id.type(), CV_32S);
|
||||
|
||||
validKeypoints.resize(mpt.rows);
|
||||
for( int i = 0; i < (int)validKeypoints.size(); i++ )
|
||||
{
|
||||
validKeypoints[i].pt.x = mpt.at<float>(i, 0);
|
||||
validKeypoints[i].pt.y = mpt.at<float>(i, 1);
|
||||
validKeypoints[i].size = msize.at<float>(i, 0);
|
||||
validKeypoints[i].angle = mangle.at<float>(i, 0);
|
||||
validKeypoints[i].response = mresponse.at<float>(i, 0);
|
||||
validKeypoints[i].octave = moctave.at<int>(i, 0);
|
||||
validKeypoints[i].class_id = mclass_id.at<int>(i, 0);
|
||||
}
|
||||
|
||||
// read descriptors
|
||||
fs["descriptors"] >> validDescriptors;
|
||||
fs.release();
|
||||
|
||||
// calc and compare keypoints
|
||||
vector<KeyPoint> calcKeypoints;
|
||||
ext->detectAndCompute(gray, Mat(), calcKeypoints, noArray(), false);
|
||||
|
||||
float countRatio = (float)validKeypoints.size() / (float)calcKeypoints.size();
|
||||
ASSERT_LT(countRatio, 1 + badCountsRatio) << "Bad keypoints count ratio.";
|
||||
ASSERT_GT(countRatio, 1 - badCountsRatio) << "Bad keypoints count ratio.";
|
||||
|
||||
int badPointCount = 0, commonPointCount = max((int)validKeypoints.size(), (int)calcKeypoints.size());
|
||||
for( size_t v = 0; v < validKeypoints.size(); v++ )
|
||||
{
|
||||
int nearestIdx = -1;
|
||||
float minDist = std::numeric_limits<float>::max();
|
||||
float angleDistOfNearest = std::numeric_limits<float>::max();
|
||||
|
||||
for( size_t c = 0; c < calcKeypoints.size(); c++ )
|
||||
{
|
||||
if( validKeypoints[v].class_id != calcKeypoints[c].class_id )
|
||||
continue;
|
||||
float curDist = (float)cv::norm( calcKeypoints[c].pt - validKeypoints[v].pt );
|
||||
if( curDist < minDist )
|
||||
{
|
||||
minDist = curDist;
|
||||
nearestIdx = (int)c;
|
||||
angleDistOfNearest = abs( calcKeypoints[c].angle - validKeypoints[v].angle );
|
||||
}
|
||||
else if( curDist == minDist ) // the keypoints whose positions are same but angles are different
|
||||
{
|
||||
float angleDist = abs( calcKeypoints[c].angle - validKeypoints[v].angle );
|
||||
if( angleDist < angleDistOfNearest )
|
||||
{
|
||||
nearestIdx = (int)c;
|
||||
angleDistOfNearest = angleDist;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( nearestIdx == -1 || !isSimilarKeypoints( validKeypoints[v], calcKeypoints[nearestIdx] ) )
|
||||
badPointCount++;
|
||||
}
|
||||
float badKeypointsRatio = (float)badPointCount / (float)commonPointCount;
|
||||
std::cout << "badKeypointsRatio: " << badKeypointsRatio << std::endl;
|
||||
ASSERT_LT( badKeypointsRatio , maxBadKeypointsRatio ) << "Bad accuracy!";
|
||||
|
||||
// Calc and compare descriptors. This uses validKeypoints for extraction.
|
||||
Mat calcDescriptors;
|
||||
ext->detectAndCompute(gray, Mat(), validKeypoints, calcDescriptors, true);
|
||||
|
||||
int dim = validDescriptors.cols;
|
||||
int badDescriptorCount = 0;
|
||||
L1<float> distance;
|
||||
|
||||
for( int i = 0; i < (int)validKeypoints.size(); i++ )
|
||||
{
|
||||
float dist = distance( validDescriptors.ptr<float>(i), calcDescriptors.ptr<float>(i), dim );
|
||||
if( dist > badDescriptorDist )
|
||||
badDescriptorCount++;
|
||||
}
|
||||
float badDescriptorRatio = (float)badDescriptorCount / (float)validKeypoints.size();
|
||||
std::cout << "badDescriptorRatio: " << badDescriptorRatio << std::endl;
|
||||
ASSERT_LT( badDescriptorRatio, maxBadDescriptorRatio ) << "Too many descriptors mismatched.";
|
||||
#endif
|
||||
}
|
||||
|
||||
}} // namespace
|
138
3rdparty/opencv-4.5.4/modules/features2d/test/test_agast.cpp
vendored
Normal file
138
3rdparty/opencv-4.5.4/modules/features2d/test/test_agast.cpp
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
/*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) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
class CV_AgastTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_AgastTest();
|
||||
~CV_AgastTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
CV_AgastTest::CV_AgastTest() {}
|
||||
CV_AgastTest::~CV_AgastTest() {}
|
||||
|
||||
void CV_AgastTest::run( int )
|
||||
{
|
||||
for(int type=0; type <= 2; ++type) {
|
||||
Mat image1 = imread(string(ts->get_data_path()) + "inpaint/orig.png");
|
||||
Mat image2 = imread(string(ts->get_data_path()) + "cameracalibration/chess9.png");
|
||||
string xml = string(ts->get_data_path()) + format("agast/result%d.xml", type);
|
||||
|
||||
if (image1.empty() || image2.empty())
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
Mat gray1, gray2;
|
||||
cvtColor(image1, gray1, COLOR_BGR2GRAY);
|
||||
cvtColor(image2, gray2, COLOR_BGR2GRAY);
|
||||
|
||||
vector<KeyPoint> keypoints1;
|
||||
vector<KeyPoint> keypoints2;
|
||||
AGAST(gray1, keypoints1, 30, true, static_cast<AgastFeatureDetector::DetectorType>(type));
|
||||
AGAST(gray2, keypoints2, (type > 0 ? 30 : 20), true, static_cast<AgastFeatureDetector::DetectorType>(type));
|
||||
|
||||
for(size_t i = 0; i < keypoints1.size(); ++i)
|
||||
{
|
||||
const KeyPoint& kp = keypoints1[i];
|
||||
cv::circle(image1, kp.pt, cvRound(kp.size/2), Scalar(255, 0, 0));
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < keypoints2.size(); ++i)
|
||||
{
|
||||
const KeyPoint& kp = keypoints2[i];
|
||||
cv::circle(image2, kp.pt, cvRound(kp.size/2), Scalar(255, 0, 0));
|
||||
}
|
||||
|
||||
Mat kps1(1, (int)(keypoints1.size() * sizeof(KeyPoint)), CV_8U, &keypoints1[0]);
|
||||
Mat kps2(1, (int)(keypoints2.size() * sizeof(KeyPoint)), CV_8U, &keypoints2[0]);
|
||||
|
||||
FileStorage fs(xml, FileStorage::READ);
|
||||
if (!fs.isOpened())
|
||||
{
|
||||
fs.open(xml, FileStorage::WRITE);
|
||||
if (!fs.isOpened())
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
return;
|
||||
}
|
||||
fs << "exp_kps1" << kps1;
|
||||
fs << "exp_kps2" << kps2;
|
||||
fs.release();
|
||||
fs.open(xml, FileStorage::READ);
|
||||
if (!fs.isOpened())
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Mat exp_kps1, exp_kps2;
|
||||
read( fs["exp_kps1"], exp_kps1, Mat() );
|
||||
read( fs["exp_kps2"], exp_kps2, Mat() );
|
||||
fs.release();
|
||||
|
||||
if ( exp_kps1.size != kps1.size || 0 != cvtest::norm(exp_kps1, kps1, NORM_L2) ||
|
||||
exp_kps2.size != kps2.size || 0 != cvtest::norm(exp_kps2, kps2, NORM_L2))
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return;
|
||||
}
|
||||
|
||||
/*cv::namedWindow("Img1"); cv::imshow("Img1", image1);
|
||||
cv::namedWindow("Img2"); cv::imshow("Img2", image2);
|
||||
cv::waitKey(0);*/
|
||||
}
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Features2d_AGAST, regression) { CV_AgastTest test; test.safe_run(); }
|
||||
|
||||
}} // namespace
|
48
3rdparty/opencv-4.5.4/modules/features2d/test/test_akaze.cpp
vendored
Normal file
48
3rdparty/opencv-4.5.4/modules/features2d/test/test_akaze.cpp
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
// 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_AKAZE, detect_and_compute_split)
|
||||
{
|
||||
Mat testImg(100, 100, CV_8U);
|
||||
RNG rng(101);
|
||||
rng.fill(testImg, RNG::UNIFORM, Scalar(0), Scalar(255), true);
|
||||
|
||||
Ptr<Feature2D> ext = AKAZE::create(AKAZE::DESCRIPTOR_MLDB, 0, 3, 0.001f, 1, 1, KAZE::DIFF_PM_G2);
|
||||
vector<KeyPoint> detAndCompKps;
|
||||
Mat desc;
|
||||
ext->detectAndCompute(testImg, noArray(), detAndCompKps, desc);
|
||||
|
||||
vector<KeyPoint> detKps;
|
||||
ext->detect(testImg, detKps);
|
||||
|
||||
ASSERT_EQ(detKps.size(), detAndCompKps.size());
|
||||
|
||||
for(size_t i = 0; i < detKps.size(); i++)
|
||||
ASSERT_EQ(detKps[i].hash(), detAndCompKps[i].hash());
|
||||
}
|
||||
|
||||
/**
|
||||
* This test is here to guard propagation of NaNs that happens on this image. NaNs are guarded
|
||||
* by debug asserts in AKAZE, which should fire for you if you are lucky.
|
||||
*
|
||||
* This test also reveals problems with uninitialized memory that happens only on this image.
|
||||
* This is very hard to hit and depends a lot on particular allocator. Run this test in valgrind and check
|
||||
* for uninitialized values if you think you are hitting this problem again.
|
||||
*/
|
||||
TEST(Features2d_AKAZE, uninitialized_and_nans)
|
||||
{
|
||||
Mat b1 = imread(cvtest::TS::ptr()->get_data_path() + "../stitching/b1.png");
|
||||
ASSERT_FALSE(b1.empty());
|
||||
|
||||
vector<KeyPoint> keypoints;
|
||||
Mat desc;
|
||||
Ptr<Feature2D> akaze = AKAZE::create();
|
||||
akaze->detectAndCompute(b1, noArray(), keypoints, desc);
|
||||
}
|
||||
|
||||
}} // namespace
|
22
3rdparty/opencv-4.5.4/modules/features2d/test/test_blobdetector.cpp
vendored
Normal file
22
3rdparty/opencv-4.5.4/modules/features2d/test/test_blobdetector.cpp
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// 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;
|
||||
params.minRepeatability = 1; // https://github.com/opencv/opencv/issues/6667
|
||||
std::vector<KeyPoint> keypoints;
|
||||
|
||||
Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);
|
||||
detector->detect(image, keypoints);
|
||||
ASSERT_NE((int) keypoints.size(), 0);
|
||||
}
|
||||
}} // namespace
|
108
3rdparty/opencv-4.5.4/modules/features2d/test/test_brisk.cpp
vendored
Normal file
108
3rdparty/opencv-4.5.4/modules/features2d/test/test_brisk.cpp
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
/*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) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
class CV_BRISKTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_BRISKTest();
|
||||
~CV_BRISKTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
CV_BRISKTest::CV_BRISKTest() {}
|
||||
CV_BRISKTest::~CV_BRISKTest() {}
|
||||
|
||||
void CV_BRISKTest::run( int )
|
||||
{
|
||||
Mat image1 = imread(string(ts->get_data_path()) + "inpaint/orig.png");
|
||||
Mat image2 = imread(string(ts->get_data_path()) + "cameracalibration/chess9.png");
|
||||
|
||||
if (image1.empty() || image2.empty())
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
Mat gray1, gray2;
|
||||
cvtColor(image1, gray1, COLOR_BGR2GRAY);
|
||||
cvtColor(image2, gray2, COLOR_BGR2GRAY);
|
||||
|
||||
Ptr<FeatureDetector> detector = BRISK::create();
|
||||
|
||||
// Check parameter get/set functions.
|
||||
BRISK* detectorTyped = dynamic_cast<BRISK*>(detector.get());
|
||||
ASSERT_NE(nullptr, detectorTyped);
|
||||
detectorTyped->setOctaves(3);
|
||||
detectorTyped->setThreshold(30);
|
||||
ASSERT_EQ(detectorTyped->getOctaves(), 3);
|
||||
ASSERT_EQ(detectorTyped->getThreshold(), 30);
|
||||
detectorTyped->setOctaves(4);
|
||||
detectorTyped->setThreshold(29);
|
||||
ASSERT_EQ(detectorTyped->getOctaves(), 4);
|
||||
ASSERT_EQ(detectorTyped->getThreshold(), 29);
|
||||
|
||||
vector<KeyPoint> keypoints1;
|
||||
vector<KeyPoint> keypoints2;
|
||||
detector->detect(image1, keypoints1);
|
||||
detector->detect(image2, keypoints2);
|
||||
|
||||
for(size_t i = 0; i < keypoints1.size(); ++i)
|
||||
{
|
||||
const KeyPoint& kp = keypoints1[i];
|
||||
ASSERT_NE(kp.angle, -1);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < keypoints2.size(); ++i)
|
||||
{
|
||||
const KeyPoint& kp = keypoints2[i];
|
||||
ASSERT_NE(kp.angle, -1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Features2d_BRISK, regression) { CV_BRISKTest test; test.safe_run(); }
|
||||
|
||||
}} // namespace
|
48
3rdparty/opencv-4.5.4/modules/features2d/test/test_descriptors_invariance.cpp
vendored
Normal file
48
3rdparty/opencv-4.5.4/modules/features2d/test/test_descriptors_invariance.cpp
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
// 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"
|
||||
#include "test_invariance_utils.hpp"
|
||||
|
||||
#include "test_descriptors_invariance.impl.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
const static std::string IMAGE_TSUKUBA = "features2d/tsukuba.png";
|
||||
const static std::string IMAGE_BIKES = "detectors_descriptors_evaluation/images_datasets/bikes/img1.png";
|
||||
#define Value(...) Values(make_tuple(__VA_ARGS__))
|
||||
|
||||
/*
|
||||
* Descriptors's rotation invariance check
|
||||
*/
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SIFT, DescriptorRotationInvariance,
|
||||
Value(IMAGE_TSUKUBA, SIFT::create(), SIFT::create(), 0.98f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(BRISK, DescriptorRotationInvariance,
|
||||
Value(IMAGE_TSUKUBA, BRISK::create(), BRISK::create(), 0.99f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ORB, DescriptorRotationInvariance,
|
||||
Value(IMAGE_TSUKUBA, ORB::create(), ORB::create(), 0.99f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(AKAZE, DescriptorRotationInvariance,
|
||||
Value(IMAGE_TSUKUBA, AKAZE::create(), AKAZE::create(), 0.99f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, DescriptorRotationInvariance,
|
||||
Value(IMAGE_TSUKUBA, AKAZE::create(AKAZE::DESCRIPTOR_KAZE), AKAZE::create(AKAZE::DESCRIPTOR_KAZE), 0.99f));
|
||||
|
||||
/*
|
||||
* Descriptor's scale invariance check
|
||||
*/
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SIFT, DescriptorScaleInvariance,
|
||||
Value(IMAGE_BIKES, SIFT::create(0, 3, 0.09), SIFT::create(0, 3, 0.09), 0.78f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(AKAZE, DescriptorScaleInvariance,
|
||||
Value(IMAGE_BIKES, AKAZE::create(), AKAZE::create(), 0.6f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, DescriptorScaleInvariance,
|
||||
Value(IMAGE_BIKES, AKAZE::create(AKAZE::DESCRIPTOR_KAZE), AKAZE::create(AKAZE::DESCRIPTOR_KAZE), 0.55f));
|
||||
|
||||
}} // namespace
|
198
3rdparty/opencv-4.5.4/modules/features2d/test/test_descriptors_invariance.impl.hpp
vendored
Normal file
198
3rdparty/opencv-4.5.4/modules/features2d/test/test_descriptors_invariance.impl.hpp
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
// 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_invariance_utils.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
#define SHOW_DEBUG_LOG 1
|
||||
|
||||
typedef tuple<std::string, Ptr<FeatureDetector>, Ptr<DescriptorExtractor>, float>
|
||||
String_FeatureDetector_DescriptorExtractor_Float_t;
|
||||
|
||||
|
||||
static
|
||||
void SetSuitableSIFTOctave(vector<KeyPoint>& keypoints,
|
||||
int firstOctave = -1, int nOctaveLayers = 3, double sigma = 1.6)
|
||||
{
|
||||
for (size_t i = 0; i < keypoints.size(); i++ )
|
||||
{
|
||||
int octv, layer;
|
||||
KeyPoint& kpt = keypoints[i];
|
||||
double octv_layer = std::log(kpt.size / sigma) / std::log(2.) - 1;
|
||||
octv = cvFloor(octv_layer);
|
||||
layer = cvRound( (octv_layer - octv) * nOctaveLayers );
|
||||
if (octv < firstOctave)
|
||||
{
|
||||
octv = firstOctave;
|
||||
layer = 0;
|
||||
}
|
||||
kpt.octave = (layer << 8) | (octv & 255);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void rotateKeyPoints(const vector<KeyPoint>& src, const Mat& H, float angle, vector<KeyPoint>& dst)
|
||||
{
|
||||
// suppose that H is rotation given from rotateImage() and angle has value passed to rotateImage()
|
||||
vector<Point2f> srcCenters, dstCenters;
|
||||
KeyPoint::convert(src, srcCenters);
|
||||
|
||||
perspectiveTransform(srcCenters, dstCenters, H);
|
||||
|
||||
dst = src;
|
||||
for(size_t i = 0; i < dst.size(); i++)
|
||||
{
|
||||
dst[i].pt = dstCenters[i];
|
||||
float dstAngle = src[i].angle + angle;
|
||||
if(dstAngle >= 360.f)
|
||||
dstAngle -= 360.f;
|
||||
dst[i].angle = dstAngle;
|
||||
}
|
||||
}
|
||||
|
||||
class DescriptorInvariance : public TestWithParam<String_FeatureDetector_DescriptorExtractor_Float_t>
|
||||
{
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
// Read test data
|
||||
const std::string filename = cvtest::TS::ptr()->get_data_path() + get<0>(GetParam());
|
||||
image0 = imread(filename);
|
||||
ASSERT_FALSE(image0.empty()) << "couldn't read input image";
|
||||
|
||||
featureDetector = get<1>(GetParam());
|
||||
descriptorExtractor = get<2>(GetParam());
|
||||
minInliersRatio = get<3>(GetParam());
|
||||
}
|
||||
|
||||
Ptr<FeatureDetector> featureDetector;
|
||||
Ptr<DescriptorExtractor> descriptorExtractor;
|
||||
float minInliersRatio;
|
||||
Mat image0;
|
||||
};
|
||||
|
||||
typedef DescriptorInvariance DescriptorScaleInvariance;
|
||||
typedef DescriptorInvariance DescriptorRotationInvariance;
|
||||
|
||||
TEST_P(DescriptorRotationInvariance, rotation)
|
||||
{
|
||||
Mat image1, mask1;
|
||||
const int borderSize = 16;
|
||||
Mat mask0(image0.size(), CV_8UC1, Scalar(0));
|
||||
mask0(Rect(borderSize, borderSize, mask0.cols - 2*borderSize, mask0.rows - 2*borderSize)).setTo(Scalar(255));
|
||||
|
||||
vector<KeyPoint> keypoints0;
|
||||
Mat descriptors0;
|
||||
featureDetector->detect(image0, keypoints0, mask0);
|
||||
std::cout << "Keypoints: " << keypoints0.size() << std::endl;
|
||||
EXPECT_GE(keypoints0.size(), 15u);
|
||||
descriptorExtractor->compute(image0, keypoints0, descriptors0);
|
||||
|
||||
BFMatcher bfmatcher(descriptorExtractor->defaultNorm());
|
||||
|
||||
const float minIntersectRatio = 0.5f;
|
||||
const int maxAngle = 360, angleStep = 15;
|
||||
for(int angle = 0; angle < maxAngle; angle += angleStep)
|
||||
{
|
||||
Mat H = rotateImage(image0, mask0, static_cast<float>(angle), image1, mask1);
|
||||
|
||||
vector<KeyPoint> keypoints1;
|
||||
rotateKeyPoints(keypoints0, H, static_cast<float>(angle), keypoints1);
|
||||
Mat descriptors1;
|
||||
descriptorExtractor->compute(image1, keypoints1, descriptors1);
|
||||
|
||||
vector<DMatch> descMatches;
|
||||
bfmatcher.match(descriptors0, descriptors1, descMatches);
|
||||
|
||||
int descInliersCount = 0;
|
||||
for(size_t m = 0; m < descMatches.size(); m++)
|
||||
{
|
||||
const KeyPoint& transformed_p0 = keypoints1[descMatches[m].queryIdx];
|
||||
const KeyPoint& p1 = keypoints1[descMatches[m].trainIdx];
|
||||
if(calcIntersectRatio(transformed_p0.pt, 0.5f * transformed_p0.size,
|
||||
p1.pt, 0.5f * p1.size) >= minIntersectRatio)
|
||||
{
|
||||
descInliersCount++;
|
||||
}
|
||||
}
|
||||
|
||||
float descInliersRatio = static_cast<float>(descInliersCount) / keypoints0.size();
|
||||
EXPECT_GE(descInliersRatio, minInliersRatio);
|
||||
#if SHOW_DEBUG_LOG
|
||||
std::cout
|
||||
<< "angle = " << angle
|
||||
<< ", inliers = " << descInliersCount
|
||||
<< ", descInliersRatio = " << static_cast<float>(descInliersCount) / keypoints0.size()
|
||||
<< std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_P(DescriptorScaleInvariance, scale)
|
||||
{
|
||||
vector<KeyPoint> keypoints0;
|
||||
featureDetector->detect(image0, keypoints0);
|
||||
std::cout << "Keypoints: " << keypoints0.size() << std::endl;
|
||||
EXPECT_GE(keypoints0.size(), 15u);
|
||||
Mat descriptors0;
|
||||
descriptorExtractor->compute(image0, keypoints0, descriptors0);
|
||||
|
||||
BFMatcher bfmatcher(descriptorExtractor->defaultNorm());
|
||||
for(int scaleIdx = 1; scaleIdx <= 3; scaleIdx++)
|
||||
{
|
||||
float scale = 1.f + scaleIdx * 0.5f;
|
||||
|
||||
Mat image1;
|
||||
resize(image0, image1, Size(), 1./scale, 1./scale, INTER_LINEAR_EXACT);
|
||||
|
||||
vector<KeyPoint> keypoints1;
|
||||
scaleKeyPoints(keypoints0, keypoints1, 1.0f/scale);
|
||||
if (featureDetector->getDefaultName() == "Feature2D.SIFT")
|
||||
{
|
||||
SetSuitableSIFTOctave(keypoints1);
|
||||
}
|
||||
Mat descriptors1;
|
||||
descriptorExtractor->compute(image1, keypoints1, descriptors1);
|
||||
|
||||
vector<DMatch> descMatches;
|
||||
bfmatcher.match(descriptors0, descriptors1, descMatches);
|
||||
|
||||
const float minIntersectRatio = 0.5f;
|
||||
int descInliersCount = 0;
|
||||
for(size_t m = 0; m < descMatches.size(); m++)
|
||||
{
|
||||
const KeyPoint& transformed_p0 = keypoints0[descMatches[m].queryIdx];
|
||||
const KeyPoint& p1 = keypoints0[descMatches[m].trainIdx];
|
||||
if(calcIntersectRatio(transformed_p0.pt, 0.5f * transformed_p0.size,
|
||||
p1.pt, 0.5f * p1.size) >= minIntersectRatio)
|
||||
{
|
||||
descInliersCount++;
|
||||
}
|
||||
}
|
||||
|
||||
float descInliersRatio = static_cast<float>(descInliersCount) / keypoints0.size();
|
||||
EXPECT_GE(descInliersRatio, minInliersRatio);
|
||||
#if SHOW_DEBUG_LOG
|
||||
std::cout
|
||||
<< "scale = " << scale
|
||||
<< ", inliers = " << descInliersCount
|
||||
<< ", descInliersRatio = " << static_cast<float>(descInliersCount) / keypoints0.size()
|
||||
<< std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#undef SHOW_DEBUG_LOG
|
||||
}} // namespace
|
||||
|
||||
namespace std {
|
||||
using namespace opencv_test;
|
||||
static inline void PrintTo(const String_FeatureDetector_DescriptorExtractor_Float_t& v, std::ostream* os)
|
||||
{
|
||||
*os << "(\"" << get<0>(v)
|
||||
<< "\", " << get<3>(v)
|
||||
<< ")";
|
||||
}
|
||||
} // namespace
|
211
3rdparty/opencv-4.5.4/modules/features2d/test/test_descriptors_regression.cpp
vendored
Normal file
211
3rdparty/opencv-4.5.4/modules/features2d/test/test_descriptors_regression.cpp
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
// 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 {
|
||||
const string FEATURES2D_DIR = "features2d";
|
||||
const string IMAGE_FILENAME = "tsukuba.png";
|
||||
const string DESCRIPTOR_DIR = FEATURES2D_DIR + "/descriptor_extractors";
|
||||
}} // namespace
|
||||
|
||||
#include "test_descriptors_regression.impl.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
/****************************************************************************************\
|
||||
* Tests registrations *
|
||||
\****************************************************************************************/
|
||||
|
||||
TEST( Features2d_DescriptorExtractor_SIFT, regression )
|
||||
{
|
||||
CV_DescriptorExtractorTest<L1<float> > test( "descriptor-sift", 1.0f,
|
||||
SIFT::create() );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_DescriptorExtractor_BRISK, regression )
|
||||
{
|
||||
CV_DescriptorExtractorTest<Hamming> test( "descriptor-brisk",
|
||||
(CV_DescriptorExtractorTest<Hamming>::DistanceType)2.f,
|
||||
BRISK::create() );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_DescriptorExtractor_ORB, regression )
|
||||
{
|
||||
// TODO adjust the parameters below
|
||||
CV_DescriptorExtractorTest<Hamming> test( "descriptor-orb",
|
||||
#if CV_NEON
|
||||
(CV_DescriptorExtractorTest<Hamming>::DistanceType)25.f,
|
||||
#else
|
||||
(CV_DescriptorExtractorTest<Hamming>::DistanceType)12.f,
|
||||
#endif
|
||||
ORB::create() );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_DescriptorExtractor_KAZE, regression )
|
||||
{
|
||||
CV_DescriptorExtractorTest< L2<float> > test( "descriptor-kaze", 0.03f,
|
||||
KAZE::create(),
|
||||
L2<float>(), KAZE::create() );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_DescriptorExtractor_AKAZE, regression )
|
||||
{
|
||||
CV_DescriptorExtractorTest<Hamming> test( "descriptor-akaze",
|
||||
(CV_DescriptorExtractorTest<Hamming>::DistanceType)(486*0.05f),
|
||||
AKAZE::create(),
|
||||
Hamming(), AKAZE::create());
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_DescriptorExtractor_AKAZE_DESCRIPTOR_KAZE, regression )
|
||||
{
|
||||
CV_DescriptorExtractorTest< L2<float> > test( "descriptor-akaze-with-kaze-desc", 0.03f,
|
||||
AKAZE::create(AKAZE::DESCRIPTOR_KAZE),
|
||||
L2<float>(), AKAZE::create(AKAZE::DESCRIPTOR_KAZE));
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_DescriptorExtractor, batch_ORB )
|
||||
{
|
||||
string path = string(cvtest::TS::ptr()->get_data_path() + "detectors_descriptors_evaluation/images_datasets/graf");
|
||||
vector<Mat> imgs, descriptors;
|
||||
vector<vector<KeyPoint> > keypoints;
|
||||
int i, n = 6;
|
||||
Ptr<ORB> orb = ORB::create();
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
string imgname = format("%s/img%d.png", path.c_str(), i+1);
|
||||
Mat img = imread(imgname, 0);
|
||||
imgs.push_back(img);
|
||||
}
|
||||
|
||||
orb->detect(imgs, keypoints);
|
||||
orb->compute(imgs, keypoints, descriptors);
|
||||
|
||||
ASSERT_EQ((int)keypoints.size(), n);
|
||||
ASSERT_EQ((int)descriptors.size(), n);
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
EXPECT_GT((int)keypoints[i].size(), 100);
|
||||
EXPECT_GT(descriptors[i].rows, 100);
|
||||
}
|
||||
}
|
||||
|
||||
TEST( Features2d_DescriptorExtractor, batch_SIFT )
|
||||
{
|
||||
string path = string(cvtest::TS::ptr()->get_data_path() + "detectors_descriptors_evaluation/images_datasets/graf");
|
||||
vector<Mat> imgs, descriptors;
|
||||
vector<vector<KeyPoint> > keypoints;
|
||||
int i, n = 6;
|
||||
Ptr<SIFT> sift = SIFT::create();
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
string imgname = format("%s/img%d.png", path.c_str(), i+1);
|
||||
Mat img = imread(imgname, 0);
|
||||
imgs.push_back(img);
|
||||
}
|
||||
|
||||
sift->detect(imgs, keypoints);
|
||||
sift->compute(imgs, keypoints, descriptors);
|
||||
|
||||
ASSERT_EQ((int)keypoints.size(), n);
|
||||
ASSERT_EQ((int)descriptors.size(), n);
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
EXPECT_GT((int)keypoints[i].size(), 100);
|
||||
EXPECT_GT(descriptors[i].rows, 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DescriptorImage : public TestWithParam<std::string>
|
||||
{
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
pattern = GetParam();
|
||||
}
|
||||
|
||||
std::string pattern;
|
||||
};
|
||||
|
||||
TEST_P(DescriptorImage, no_crash)
|
||||
{
|
||||
vector<String> fnames;
|
||||
glob(cvtest::TS::ptr()->get_data_path() + pattern, fnames, false);
|
||||
sort(fnames.begin(), fnames.end());
|
||||
|
||||
Ptr<AKAZE> akaze_mldb = AKAZE::create(AKAZE::DESCRIPTOR_MLDB);
|
||||
Ptr<AKAZE> akaze_mldb_upright = AKAZE::create(AKAZE::DESCRIPTOR_MLDB_UPRIGHT);
|
||||
Ptr<AKAZE> akaze_mldb_256 = AKAZE::create(AKAZE::DESCRIPTOR_MLDB, 256);
|
||||
Ptr<AKAZE> akaze_mldb_upright_256 = AKAZE::create(AKAZE::DESCRIPTOR_MLDB_UPRIGHT, 256);
|
||||
Ptr<AKAZE> akaze_kaze = AKAZE::create(AKAZE::DESCRIPTOR_KAZE);
|
||||
Ptr<AKAZE> akaze_kaze_upright = AKAZE::create(AKAZE::DESCRIPTOR_KAZE_UPRIGHT);
|
||||
Ptr<ORB> orb = ORB::create();
|
||||
Ptr<KAZE> kaze = KAZE::create();
|
||||
Ptr<BRISK> brisk = BRISK::create();
|
||||
size_t n = fnames.size();
|
||||
vector<KeyPoint> keypoints;
|
||||
Mat descriptors;
|
||||
orb->setMaxFeatures(5000);
|
||||
|
||||
for(size_t i = 0; i < n; i++ )
|
||||
{
|
||||
printf("%d. image: %s:\n", (int)i, fnames[i].c_str());
|
||||
if( strstr(fnames[i].c_str(), "MP.png") != 0 )
|
||||
{
|
||||
printf("\tskip\n");
|
||||
continue;
|
||||
}
|
||||
bool checkCount = strstr(fnames[i].c_str(), "templ.png") == 0;
|
||||
|
||||
Mat img = imread(fnames[i], -1);
|
||||
|
||||
printf("\t%dx%d\n", img.cols, img.rows);
|
||||
|
||||
#define TEST_DETECTOR(name, descriptor) \
|
||||
keypoints.clear(); descriptors.release(); \
|
||||
printf("\t" name "\n"); fflush(stdout); \
|
||||
descriptor->detectAndCompute(img, noArray(), keypoints, descriptors); \
|
||||
printf("\t\t\t(%d keypoints, descriptor size = %d)\n", (int)keypoints.size(), descriptors.cols); fflush(stdout); \
|
||||
if (checkCount) \
|
||||
{ \
|
||||
EXPECT_GT((int)keypoints.size(), 0); \
|
||||
} \
|
||||
ASSERT_EQ(descriptors.rows, (int)keypoints.size());
|
||||
|
||||
TEST_DETECTOR("AKAZE:MLDB", akaze_mldb);
|
||||
TEST_DETECTOR("AKAZE:MLDB_UPRIGHT", akaze_mldb_upright);
|
||||
TEST_DETECTOR("AKAZE:MLDB_256", akaze_mldb_256);
|
||||
TEST_DETECTOR("AKAZE:MLDB_UPRIGHT_256", akaze_mldb_upright_256);
|
||||
TEST_DETECTOR("AKAZE:KAZE", akaze_kaze);
|
||||
TEST_DETECTOR("AKAZE:KAZE_UPRIGHT", akaze_kaze_upright);
|
||||
TEST_DETECTOR("KAZE", kaze);
|
||||
TEST_DETECTOR("ORB", orb);
|
||||
TEST_DETECTOR("BRISK", brisk);
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Features2d, DescriptorImage,
|
||||
testing::Values(
|
||||
"shared/lena.png",
|
||||
"shared/box*.png",
|
||||
"shared/fruits*.png",
|
||||
"shared/airplane.png",
|
||||
"shared/graffiti.png",
|
||||
"shared/1_itseez-0001*.png",
|
||||
"shared/pic*.png",
|
||||
"shared/templ.png"
|
||||
)
|
||||
);
|
||||
|
||||
}} // namespace
|
298
3rdparty/opencv-4.5.4/modules/features2d/test/test_descriptors_regression.impl.hpp
vendored
Normal file
298
3rdparty/opencv-4.5.4/modules/features2d/test/test_descriptors_regression.impl.hpp
vendored
Normal file
@ -0,0 +1,298 @@
|
||||
// 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
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
/****************************************************************************************\
|
||||
* Regression tests for descriptor extractors. *
|
||||
\****************************************************************************************/
|
||||
static void writeMatInBin( const Mat& mat, const string& filename )
|
||||
{
|
||||
FILE* f = fopen( filename.c_str(), "wb");
|
||||
if( f )
|
||||
{
|
||||
CV_Assert(4 == sizeof(int));
|
||||
int type = mat.type();
|
||||
fwrite( (void*)&mat.rows, sizeof(int), 1, f );
|
||||
fwrite( (void*)&mat.cols, sizeof(int), 1, f );
|
||||
fwrite( (void*)&type, sizeof(int), 1, f );
|
||||
int dataSize = (int)(mat.step * mat.rows);
|
||||
fwrite( (void*)&dataSize, sizeof(int), 1, f );
|
||||
fwrite( (void*)mat.ptr(), 1, dataSize, f );
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
static Mat readMatFromBin( const string& filename )
|
||||
{
|
||||
FILE* f = fopen( filename.c_str(), "rb" );
|
||||
if( f )
|
||||
{
|
||||
CV_Assert(4 == sizeof(int));
|
||||
int rows, cols, type, dataSize;
|
||||
size_t elements_read1 = fread( (void*)&rows, sizeof(int), 1, f );
|
||||
size_t elements_read2 = fread( (void*)&cols, sizeof(int), 1, f );
|
||||
size_t elements_read3 = fread( (void*)&type, sizeof(int), 1, f );
|
||||
size_t elements_read4 = fread( (void*)&dataSize, sizeof(int), 1, f );
|
||||
CV_Assert(elements_read1 == 1 && elements_read2 == 1 && elements_read3 == 1 && elements_read4 == 1);
|
||||
|
||||
int step = dataSize / rows / CV_ELEM_SIZE(type);
|
||||
CV_Assert(step >= cols);
|
||||
|
||||
Mat returnMat = Mat(rows, step, type).colRange(0, cols);
|
||||
|
||||
size_t elements_read = fread( returnMat.ptr(), 1, dataSize, f );
|
||||
CV_Assert(elements_read == (size_t)(dataSize));
|
||||
|
||||
fclose(f);
|
||||
|
||||
return returnMat;
|
||||
}
|
||||
return Mat();
|
||||
}
|
||||
|
||||
template<class Distance>
|
||||
class CV_DescriptorExtractorTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
typedef typename Distance::ValueType ValueType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
CV_DescriptorExtractorTest( const string _name, DistanceType _maxDist, const Ptr<DescriptorExtractor>& _dextractor,
|
||||
Distance d = Distance(), Ptr<FeatureDetector> _detector = Ptr<FeatureDetector>()):
|
||||
name(_name), maxDist(_maxDist), dextractor(_dextractor), distance(d) , detector(_detector) {}
|
||||
|
||||
~CV_DescriptorExtractorTest()
|
||||
{
|
||||
}
|
||||
protected:
|
||||
virtual void createDescriptorExtractor() {}
|
||||
|
||||
void compareDescriptors( const Mat& validDescriptors, const Mat& calcDescriptors )
|
||||
{
|
||||
if( validDescriptors.size != calcDescriptors.size || validDescriptors.type() != calcDescriptors.type() )
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "Valid and computed descriptors matrices must have the same size and type.\n");
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
CV_Assert( DataType<ValueType>::type == validDescriptors.type() );
|
||||
|
||||
int dimension = validDescriptors.cols;
|
||||
DistanceType curMaxDist = 0;
|
||||
size_t exact_count = 0, failed_count = 0;
|
||||
for( int y = 0; y < validDescriptors.rows; y++ )
|
||||
{
|
||||
DistanceType dist = distance( validDescriptors.ptr<ValueType>(y), calcDescriptors.ptr<ValueType>(y), dimension );
|
||||
if (dist == 0)
|
||||
exact_count++;
|
||||
if( dist > curMaxDist )
|
||||
{
|
||||
if (dist > maxDist)
|
||||
failed_count++;
|
||||
curMaxDist = dist;
|
||||
}
|
||||
#if 0
|
||||
if (dist > 0)
|
||||
{
|
||||
std::cout << "i=" << y << " fail_count=" << failed_count << " dist=" << dist << std::endl;
|
||||
std::cout << "valid: " << validDescriptors.row(y) << std::endl;
|
||||
std::cout << " calc: " << calcDescriptors.row(y) << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float exact_percents = (100 * (float)exact_count / validDescriptors.rows);
|
||||
float failed_percents = (100 * (float)failed_count / validDescriptors.rows);
|
||||
std::stringstream ss;
|
||||
ss << "Exact count (dist == 0): " << exact_count << " (" << (int)exact_percents << "%)" << std::endl
|
||||
<< "Failed count (dist > " << maxDist << "): " << failed_count << " (" << (int)failed_percents << "%)" << std::endl
|
||||
<< "Max distance between valid and computed descriptors (" << validDescriptors.size() << "): " << curMaxDist;
|
||||
EXPECT_LE(failed_percents, 20.0f);
|
||||
std::cout << ss.str() << std::endl;
|
||||
}
|
||||
|
||||
void emptyDataTest()
|
||||
{
|
||||
assert( dextractor );
|
||||
|
||||
// One image.
|
||||
Mat image;
|
||||
vector<KeyPoint> keypoints;
|
||||
Mat descriptors;
|
||||
|
||||
try
|
||||
{
|
||||
dextractor->compute( image, keypoints, descriptors );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "compute() on empty image and empty keypoints must not generate exception (1).\n");
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
}
|
||||
|
||||
RNG rng;
|
||||
image = cvtest::randomMat(rng, Size(50, 50), CV_8UC3, 0, 255, false);
|
||||
try
|
||||
{
|
||||
dextractor->compute( image, keypoints, descriptors );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "compute() on nonempty image and empty keypoints must not generate exception (1).\n");
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
}
|
||||
|
||||
// Several images.
|
||||
vector<Mat> images;
|
||||
vector<vector<KeyPoint> > keypointsCollection;
|
||||
vector<Mat> descriptorsCollection;
|
||||
try
|
||||
{
|
||||
dextractor->compute( images, keypointsCollection, descriptorsCollection );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "compute() on empty images and empty keypoints collection must not generate exception (2).\n");
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
}
|
||||
}
|
||||
|
||||
void regressionTest()
|
||||
{
|
||||
assert( dextractor );
|
||||
|
||||
// Read the test image.
|
||||
string imgFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + IMAGE_FILENAME;
|
||||
Mat img = imread( imgFilename );
|
||||
if( img.empty() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Image %s can not be read.\n", imgFilename.c_str() );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
const std::string keypoints_filename = string(ts->get_data_path()) +
|
||||
(detector.empty()
|
||||
? (FEATURES2D_DIR + "/" + std::string("keypoints.xml.gz"))
|
||||
: (DESCRIPTOR_DIR + "/" + name + "_keypoints.xml.gz"));
|
||||
FileStorage fs(keypoints_filename, FileStorage::READ);
|
||||
|
||||
vector<KeyPoint> keypoints;
|
||||
EXPECT_TRUE(fs.isOpened()) << "Keypoint testdata is missing. Re-computing and re-writing keypoints testdata...";
|
||||
if (!fs.isOpened())
|
||||
{
|
||||
fs.open(keypoints_filename, FileStorage::WRITE);
|
||||
ASSERT_TRUE(fs.isOpened()) << "File for writing keypoints can not be opened.";
|
||||
if (detector.empty())
|
||||
{
|
||||
Ptr<ORB> fd = ORB::create();
|
||||
fd->detect(img, keypoints);
|
||||
}
|
||||
else
|
||||
{
|
||||
detector->detect(img, keypoints);
|
||||
}
|
||||
write(fs, "keypoints", keypoints);
|
||||
fs.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
read(fs.getFirstTopLevelNode(), keypoints);
|
||||
fs.release();
|
||||
}
|
||||
|
||||
if(!detector.empty())
|
||||
{
|
||||
vector<KeyPoint> calcKeypoints;
|
||||
detector->detect(img, calcKeypoints);
|
||||
// TODO validate received keypoints
|
||||
int diff = abs((int)calcKeypoints.size() - (int)keypoints.size());
|
||||
if (diff > 0)
|
||||
{
|
||||
std::cout << "Keypoints difference: " << diff << std::endl;
|
||||
EXPECT_LE(diff, (int)(keypoints.size() * 0.03f));
|
||||
}
|
||||
}
|
||||
ASSERT_FALSE(keypoints.empty());
|
||||
{
|
||||
Mat calcDescriptors;
|
||||
double t = (double)getTickCount();
|
||||
dextractor->compute(img, keypoints, calcDescriptors);
|
||||
t = getTickCount() - t;
|
||||
ts->printf(cvtest::TS::LOG, "\nAverage time of computing one descriptor = %g ms.\n", t/((double)getTickFrequency()*1000.)/calcDescriptors.rows);
|
||||
|
||||
if (calcDescriptors.rows != (int)keypoints.size())
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Count of computed descriptors and keypoints count must be equal.\n" );
|
||||
ts->printf( cvtest::TS::LOG, "Count of keypoints is %d.\n", (int)keypoints.size() );
|
||||
ts->printf( cvtest::TS::LOG, "Count of computed descriptors is %d.\n", calcDescriptors.rows );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
|
||||
if (calcDescriptors.cols != dextractor->descriptorSize() || calcDescriptors.type() != dextractor->descriptorType())
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Incorrect descriptor size or descriptor type.\n" );
|
||||
ts->printf( cvtest::TS::LOG, "Expected size is %d.\n", dextractor->descriptorSize() );
|
||||
ts->printf( cvtest::TS::LOG, "Calculated size is %d.\n", calcDescriptors.cols );
|
||||
ts->printf( cvtest::TS::LOG, "Expected type is %d.\n", dextractor->descriptorType() );
|
||||
ts->printf( cvtest::TS::LOG, "Calculated type is %d.\n", calcDescriptors.type() );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO read and write descriptor extractor parameters and check them
|
||||
Mat validDescriptors = readDescriptors();
|
||||
EXPECT_FALSE(validDescriptors.empty()) << "Descriptors testdata is missing. Re-writing descriptors testdata...";
|
||||
if (!validDescriptors.empty())
|
||||
{
|
||||
compareDescriptors(validDescriptors, calcDescriptors);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_TRUE(writeDescriptors(calcDescriptors)) << "Descriptors can not be written.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run(int)
|
||||
{
|
||||
createDescriptorExtractor();
|
||||
if( !dextractor )
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "Descriptor extractor is empty.\n");
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
emptyDataTest();
|
||||
regressionTest();
|
||||
|
||||
ts->set_failed_test_info( cvtest::TS::OK );
|
||||
}
|
||||
|
||||
virtual Mat readDescriptors()
|
||||
{
|
||||
Mat res = readMatFromBin( string(ts->get_data_path()) + DESCRIPTOR_DIR + "/" + string(name) );
|
||||
return res;
|
||||
}
|
||||
|
||||
virtual bool writeDescriptors( Mat& descs )
|
||||
{
|
||||
writeMatInBin( descs, string(ts->get_data_path()) + DESCRIPTOR_DIR + "/" + string(name) );
|
||||
return true;
|
||||
}
|
||||
|
||||
string name;
|
||||
const DistanceType maxDist;
|
||||
Ptr<DescriptorExtractor> dextractor;
|
||||
Distance distance;
|
||||
Ptr<FeatureDetector> detector;
|
||||
|
||||
private:
|
||||
CV_DescriptorExtractorTest& operator=(const CV_DescriptorExtractorTest&) { return *this; }
|
||||
};
|
||||
|
||||
}} // namespace
|
57
3rdparty/opencv-4.5.4/modules/features2d/test/test_detectors_invariance.cpp
vendored
Normal file
57
3rdparty/opencv-4.5.4/modules/features2d/test/test_detectors_invariance.cpp
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
// 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"
|
||||
#include "test_invariance_utils.hpp"
|
||||
|
||||
#include "test_detectors_invariance.impl.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
const static std::string IMAGE_TSUKUBA = "features2d/tsukuba.png";
|
||||
const static std::string IMAGE_BIKES = "detectors_descriptors_evaluation/images_datasets/bikes/img1.png";
|
||||
#define Value(...) Values(make_tuple(__VA_ARGS__))
|
||||
|
||||
/*
|
||||
* Detector's rotation invariance check
|
||||
*/
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SIFT, DetectorRotationInvariance,
|
||||
Value(IMAGE_TSUKUBA, SIFT::create(), 0.45f, 0.70f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(BRISK, DetectorRotationInvariance,
|
||||
Value(IMAGE_TSUKUBA, BRISK::create(), 0.45f, 0.76f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ORB, DetectorRotationInvariance,
|
||||
Value(IMAGE_TSUKUBA, ORB::create(), 0.5f, 0.76f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(AKAZE, DetectorRotationInvariance,
|
||||
Value(IMAGE_TSUKUBA, AKAZE::create(), 0.5f, 0.71f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, DetectorRotationInvariance,
|
||||
Value(IMAGE_TSUKUBA, AKAZE::create(AKAZE::DESCRIPTOR_KAZE), 0.5f, 0.71f));
|
||||
|
||||
/*
|
||||
* Detector's scale invariance check
|
||||
*/
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SIFT, DetectorScaleInvariance,
|
||||
Value(IMAGE_BIKES, SIFT::create(0, 3, 0.09), 0.65f, 0.98f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(BRISK, DetectorScaleInvariance,
|
||||
Value(IMAGE_BIKES, BRISK::create(), 0.08f, 0.49f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ORB, DetectorScaleInvariance,
|
||||
Value(IMAGE_BIKES, ORB::create(), 0.08f, 0.49f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(KAZE, DetectorScaleInvariance,
|
||||
Value(IMAGE_BIKES, KAZE::create(), 0.08f, 0.49f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(AKAZE, DetectorScaleInvariance,
|
||||
Value(IMAGE_BIKES, AKAZE::create(), 0.08f, 0.49f));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, DetectorScaleInvariance,
|
||||
Value(IMAGE_BIKES, AKAZE::create(AKAZE::DESCRIPTOR_KAZE), 0.08f, 0.49f));
|
||||
|
||||
}} // namespace
|
227
3rdparty/opencv-4.5.4/modules/features2d/test/test_detectors_invariance.impl.hpp
vendored
Normal file
227
3rdparty/opencv-4.5.4/modules/features2d/test/test_detectors_invariance.impl.hpp
vendored
Normal file
@ -0,0 +1,227 @@
|
||||
// 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_invariance_utils.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
#define SHOW_DEBUG_LOG 1
|
||||
|
||||
typedef tuple<std::string, Ptr<FeatureDetector>, float, float> String_FeatureDetector_Float_Float_t;
|
||||
|
||||
|
||||
static
|
||||
void matchKeyPoints(const vector<KeyPoint>& keypoints0, const Mat& H,
|
||||
const vector<KeyPoint>& keypoints1,
|
||||
vector<DMatch>& matches)
|
||||
{
|
||||
vector<Point2f> points0;
|
||||
KeyPoint::convert(keypoints0, points0);
|
||||
Mat points0t;
|
||||
if(H.empty())
|
||||
points0t = Mat(points0);
|
||||
else
|
||||
perspectiveTransform(Mat(points0), points0t, H);
|
||||
|
||||
matches.clear();
|
||||
vector<uchar> usedMask(keypoints1.size(), 0);
|
||||
for(int i0 = 0; i0 < static_cast<int>(keypoints0.size()); i0++)
|
||||
{
|
||||
int nearestPointIndex = -1;
|
||||
float maxIntersectRatio = 0.f;
|
||||
const float r0 = 0.5f * keypoints0[i0].size;
|
||||
for(size_t i1 = 0; i1 < keypoints1.size(); i1++)
|
||||
{
|
||||
if(nearestPointIndex >= 0 && usedMask[i1])
|
||||
continue;
|
||||
|
||||
float r1 = 0.5f * keypoints1[i1].size;
|
||||
float intersectRatio = calcIntersectRatio(points0t.at<Point2f>(i0), r0,
|
||||
keypoints1[i1].pt, r1);
|
||||
if(intersectRatio > maxIntersectRatio)
|
||||
{
|
||||
maxIntersectRatio = intersectRatio;
|
||||
nearestPointIndex = static_cast<int>(i1);
|
||||
}
|
||||
}
|
||||
|
||||
matches.push_back(DMatch(i0, nearestPointIndex, maxIntersectRatio));
|
||||
if(nearestPointIndex >= 0)
|
||||
usedMask[nearestPointIndex] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
class DetectorInvariance : public TestWithParam<String_FeatureDetector_Float_Float_t>
|
||||
{
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
// Read test data
|
||||
const std::string filename = cvtest::TS::ptr()->get_data_path() + get<0>(GetParam());
|
||||
image0 = imread(filename);
|
||||
ASSERT_FALSE(image0.empty()) << "couldn't read input image";
|
||||
|
||||
featureDetector = get<1>(GetParam());
|
||||
minKeyPointMatchesRatio = get<2>(GetParam());
|
||||
minInliersRatio = get<3>(GetParam());
|
||||
}
|
||||
|
||||
Ptr<FeatureDetector> featureDetector;
|
||||
float minKeyPointMatchesRatio;
|
||||
float minInliersRatio;
|
||||
Mat image0;
|
||||
};
|
||||
|
||||
typedef DetectorInvariance DetectorScaleInvariance;
|
||||
typedef DetectorInvariance DetectorRotationInvariance;
|
||||
|
||||
TEST_P(DetectorRotationInvariance, rotation)
|
||||
{
|
||||
Mat image1, mask1;
|
||||
const int borderSize = 16;
|
||||
Mat mask0(image0.size(), CV_8UC1, Scalar(0));
|
||||
mask0(Rect(borderSize, borderSize, mask0.cols - 2*borderSize, mask0.rows - 2*borderSize)).setTo(Scalar(255));
|
||||
|
||||
vector<KeyPoint> keypoints0;
|
||||
featureDetector->detect(image0, keypoints0, mask0);
|
||||
EXPECT_GE(keypoints0.size(), 15u);
|
||||
|
||||
const int maxAngle = 360, angleStep = 15;
|
||||
for(int angle = 0; angle < maxAngle; angle += angleStep)
|
||||
{
|
||||
Mat H = rotateImage(image0, mask0, static_cast<float>(angle), image1, mask1);
|
||||
|
||||
vector<KeyPoint> keypoints1;
|
||||
featureDetector->detect(image1, keypoints1, mask1);
|
||||
|
||||
vector<DMatch> matches;
|
||||
matchKeyPoints(keypoints0, H, keypoints1, matches);
|
||||
|
||||
int angleInliersCount = 0;
|
||||
|
||||
const float minIntersectRatio = 0.5f;
|
||||
int keyPointMatchesCount = 0;
|
||||
for(size_t m = 0; m < matches.size(); m++)
|
||||
{
|
||||
if(matches[m].distance < minIntersectRatio)
|
||||
continue;
|
||||
|
||||
keyPointMatchesCount++;
|
||||
|
||||
// Check does this inlier have consistent angles
|
||||
const float maxAngleDiff = 15.f; // grad
|
||||
float angle0 = keypoints0[matches[m].queryIdx].angle;
|
||||
float angle1 = keypoints1[matches[m].trainIdx].angle;
|
||||
ASSERT_FALSE(angle0 == -1 || angle1 == -1) << "Given FeatureDetector is not rotation invariant, it can not be tested here.";
|
||||
ASSERT_GE(angle0, 0.f);
|
||||
ASSERT_LT(angle0, 360.f);
|
||||
ASSERT_GE(angle1, 0.f);
|
||||
ASSERT_LT(angle1, 360.f);
|
||||
|
||||
float rotAngle0 = angle0 + angle;
|
||||
if(rotAngle0 >= 360.f)
|
||||
rotAngle0 -= 360.f;
|
||||
|
||||
float angleDiff = std::max(rotAngle0, angle1) - std::min(rotAngle0, angle1);
|
||||
angleDiff = std::min(angleDiff, static_cast<float>(360.f - angleDiff));
|
||||
ASSERT_GE(angleDiff, 0.f);
|
||||
bool isAngleCorrect = angleDiff < maxAngleDiff;
|
||||
if(isAngleCorrect)
|
||||
angleInliersCount++;
|
||||
}
|
||||
|
||||
float keyPointMatchesRatio = static_cast<float>(keyPointMatchesCount) / keypoints0.size();
|
||||
EXPECT_GE(keyPointMatchesRatio, minKeyPointMatchesRatio) << "angle: " << angle;
|
||||
|
||||
if(keyPointMatchesCount)
|
||||
{
|
||||
float angleInliersRatio = static_cast<float>(angleInliersCount) / keyPointMatchesCount;
|
||||
EXPECT_GE(angleInliersRatio, minInliersRatio) << "angle: " << angle;
|
||||
}
|
||||
#if SHOW_DEBUG_LOG
|
||||
std::cout
|
||||
<< "angle = " << angle
|
||||
<< ", keypoints = " << keypoints1.size()
|
||||
<< ", keyPointMatchesRatio = " << keyPointMatchesRatio
|
||||
<< ", angleInliersRatio = " << (keyPointMatchesCount ? (static_cast<float>(angleInliersCount) / keyPointMatchesCount) : 0)
|
||||
<< std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(DetectorScaleInvariance, scale)
|
||||
{
|
||||
vector<KeyPoint> keypoints0;
|
||||
featureDetector->detect(image0, keypoints0);
|
||||
EXPECT_GE(keypoints0.size(), 15u);
|
||||
|
||||
for(int scaleIdx = 1; scaleIdx <= 3; scaleIdx++)
|
||||
{
|
||||
float scale = 1.f + scaleIdx * 0.5f;
|
||||
Mat image1;
|
||||
resize(image0, image1, Size(), 1./scale, 1./scale, INTER_LINEAR_EXACT);
|
||||
|
||||
vector<KeyPoint> keypoints1, osiKeypoints1; // osi - original size image
|
||||
featureDetector->detect(image1, keypoints1);
|
||||
EXPECT_GE(keypoints1.size(), 15u);
|
||||
EXPECT_LE(keypoints1.size(), keypoints0.size()) << "Strange behavior of the detector. "
|
||||
"It gives more points count in an image of the smaller size.";
|
||||
|
||||
scaleKeyPoints(keypoints1, osiKeypoints1, scale);
|
||||
vector<DMatch> matches;
|
||||
// image1 is query image (it's reduced image0)
|
||||
// image0 is train image
|
||||
matchKeyPoints(osiKeypoints1, Mat(), keypoints0, matches);
|
||||
|
||||
const float minIntersectRatio = 0.5f;
|
||||
int keyPointMatchesCount = 0;
|
||||
int scaleInliersCount = 0;
|
||||
|
||||
for(size_t m = 0; m < matches.size(); m++)
|
||||
{
|
||||
if(matches[m].distance < minIntersectRatio)
|
||||
continue;
|
||||
|
||||
keyPointMatchesCount++;
|
||||
|
||||
// Check does this inlier have consistent sizes
|
||||
const float maxSizeDiff = 0.8f;//0.9f; // grad
|
||||
float size0 = keypoints0[matches[m].trainIdx].size;
|
||||
float size1 = osiKeypoints1[matches[m].queryIdx].size;
|
||||
ASSERT_GT(size0, 0);
|
||||
ASSERT_GT(size1, 0);
|
||||
if(std::min(size0, size1) > maxSizeDiff * std::max(size0, size1))
|
||||
scaleInliersCount++;
|
||||
}
|
||||
|
||||
float keyPointMatchesRatio = static_cast<float>(keyPointMatchesCount) / keypoints1.size();
|
||||
EXPECT_GE(keyPointMatchesRatio, minKeyPointMatchesRatio);
|
||||
|
||||
if(keyPointMatchesCount)
|
||||
{
|
||||
float scaleInliersRatio = static_cast<float>(scaleInliersCount) / keyPointMatchesCount;
|
||||
EXPECT_GE(scaleInliersRatio, minInliersRatio);
|
||||
}
|
||||
#if SHOW_DEBUG_LOG
|
||||
std::cout
|
||||
<< "scale = " << scale
|
||||
<< ", keyPointMatchesRatio = " << keyPointMatchesRatio
|
||||
<< ", scaleInliersRatio = " << (keyPointMatchesCount ? static_cast<float>(scaleInliersCount) / keyPointMatchesCount : 0)
|
||||
<< std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#undef SHOW_DEBUG_LOG
|
||||
}} // namespace
|
||||
|
||||
namespace std {
|
||||
using namespace opencv_test;
|
||||
static inline void PrintTo(const String_FeatureDetector_Float_Float_t& v, std::ostream* os)
|
||||
{
|
||||
*os << "(\"" << get<0>(v)
|
||||
<< "\", " << get<2>(v)
|
||||
<< ", " << get<3>(v)
|
||||
<< ")";
|
||||
}
|
||||
} // namespace
|
89
3rdparty/opencv-4.5.4/modules/features2d/test/test_detectors_regression.cpp
vendored
Normal file
89
3rdparty/opencv-4.5.4/modules/features2d/test/test_detectors_regression.cpp
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
// 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 {
|
||||
const string FEATURES2D_DIR = "features2d";
|
||||
const string IMAGE_FILENAME = "tsukuba.png";
|
||||
const string DETECTOR_DIR = FEATURES2D_DIR + "/feature_detectors";
|
||||
}} // namespace
|
||||
|
||||
#include "test_detectors_regression.impl.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
/****************************************************************************************\
|
||||
* Tests registrations *
|
||||
\****************************************************************************************/
|
||||
|
||||
TEST( Features2d_Detector_SIFT, regression )
|
||||
{
|
||||
CV_FeatureDetectorTest test( "detector-sift", SIFT::create() );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_Detector_BRISK, regression )
|
||||
{
|
||||
CV_FeatureDetectorTest test( "detector-brisk", BRISK::create() );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_Detector_FAST, regression )
|
||||
{
|
||||
CV_FeatureDetectorTest test( "detector-fast", FastFeatureDetector::create() );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_Detector_AGAST, regression )
|
||||
{
|
||||
CV_FeatureDetectorTest test( "detector-agast", AgastFeatureDetector::create() );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_Detector_GFTT, regression )
|
||||
{
|
||||
CV_FeatureDetectorTest test( "detector-gftt", GFTTDetector::create() );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_Detector_Harris, regression )
|
||||
{
|
||||
Ptr<GFTTDetector> gftt = GFTTDetector::create();
|
||||
gftt->setHarrisDetector(true);
|
||||
CV_FeatureDetectorTest test( "detector-harris", gftt);
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_Detector_MSER, DISABLED_regression )
|
||||
{
|
||||
CV_FeatureDetectorTest test( "detector-mser", MSER::create() );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_Detector_ORB, regression )
|
||||
{
|
||||
CV_FeatureDetectorTest test( "detector-orb", ORB::create() );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_Detector_KAZE, regression )
|
||||
{
|
||||
CV_FeatureDetectorTest test( "detector-kaze", KAZE::create() );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_Detector_AKAZE, regression )
|
||||
{
|
||||
CV_FeatureDetectorTest test( "detector-akaze", AKAZE::create() );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST( Features2d_Detector_AKAZE_DESCRIPTOR_KAZE, regression )
|
||||
{
|
||||
CV_FeatureDetectorTest test( "detector-akaze-with-kaze-desc", AKAZE::create(AKAZE::DESCRIPTOR_KAZE) );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
}} // namespace
|
201
3rdparty/opencv-4.5.4/modules/features2d/test/test_detectors_regression.impl.hpp
vendored
Normal file
201
3rdparty/opencv-4.5.4/modules/features2d/test/test_detectors_regression.impl.hpp
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
// 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
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
/****************************************************************************************\
|
||||
* Regression tests for feature detectors comparing keypoints. *
|
||||
\****************************************************************************************/
|
||||
|
||||
class CV_FeatureDetectorTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_FeatureDetectorTest( const string& _name, const Ptr<FeatureDetector>& _fdetector ) :
|
||||
name(_name), fdetector(_fdetector) {}
|
||||
|
||||
protected:
|
||||
bool isSimilarKeypoints( const KeyPoint& p1, const KeyPoint& p2 );
|
||||
void compareKeypointSets( const vector<KeyPoint>& validKeypoints, const vector<KeyPoint>& calcKeypoints );
|
||||
|
||||
void emptyDataTest();
|
||||
void regressionTest(); // TODO test of detect() with mask
|
||||
|
||||
virtual void run( int );
|
||||
|
||||
string name;
|
||||
Ptr<FeatureDetector> fdetector;
|
||||
};
|
||||
|
||||
void CV_FeatureDetectorTest::emptyDataTest()
|
||||
{
|
||||
// One image.
|
||||
Mat image;
|
||||
vector<KeyPoint> keypoints;
|
||||
try
|
||||
{
|
||||
fdetector->detect( image, keypoints );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "detect() on empty image must not generate exception (1).\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
|
||||
if( !keypoints.empty() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "detect() on empty image must return empty keypoints vector (1).\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
|
||||
// Several images.
|
||||
vector<Mat> images;
|
||||
vector<vector<KeyPoint> > keypointCollection;
|
||||
try
|
||||
{
|
||||
fdetector->detect( images, keypointCollection );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "detect() on empty image vector must not generate exception (2).\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
}
|
||||
|
||||
bool CV_FeatureDetectorTest::isSimilarKeypoints( const KeyPoint& p1, const KeyPoint& p2 )
|
||||
{
|
||||
const float maxPtDif = 1.f;
|
||||
const float maxSizeDif = 1.f;
|
||||
const float maxAngleDif = 2.f;
|
||||
const float maxResponseDif = 0.1f;
|
||||
|
||||
float dist = (float)cv::norm( p1.pt - p2.pt );
|
||||
return (dist < maxPtDif &&
|
||||
fabs(p1.size - p2.size) < maxSizeDif &&
|
||||
abs(p1.angle - p2.angle) < maxAngleDif &&
|
||||
abs(p1.response - p2.response) < maxResponseDif &&
|
||||
p1.octave == p2.octave &&
|
||||
p1.class_id == p2.class_id );
|
||||
}
|
||||
|
||||
void CV_FeatureDetectorTest::compareKeypointSets( const vector<KeyPoint>& validKeypoints, const vector<KeyPoint>& calcKeypoints )
|
||||
{
|
||||
const float maxCountRatioDif = 0.01f;
|
||||
|
||||
// Compare counts of validation and calculated keypoints.
|
||||
float countRatio = (float)validKeypoints.size() / (float)calcKeypoints.size();
|
||||
if( countRatio < 1 - maxCountRatioDif || countRatio > 1.f + maxCountRatioDif )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Bad keypoints count ratio (validCount = %d, calcCount = %d).\n",
|
||||
validKeypoints.size(), calcKeypoints.size() );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
|
||||
int progress = 0, progressCount = (int)(validKeypoints.size() * calcKeypoints.size());
|
||||
int badPointCount = 0, commonPointCount = max((int)validKeypoints.size(), (int)calcKeypoints.size());
|
||||
for( size_t v = 0; v < validKeypoints.size(); v++ )
|
||||
{
|
||||
int nearestIdx = -1;
|
||||
float minDist = std::numeric_limits<float>::max();
|
||||
|
||||
for( size_t c = 0; c < calcKeypoints.size(); c++ )
|
||||
{
|
||||
progress = update_progress( progress, (int)(v*calcKeypoints.size() + c), progressCount, 0 );
|
||||
float curDist = (float)cv::norm( calcKeypoints[c].pt - validKeypoints[v].pt );
|
||||
if( curDist < minDist )
|
||||
{
|
||||
minDist = curDist;
|
||||
nearestIdx = (int)c;
|
||||
}
|
||||
}
|
||||
|
||||
assert( minDist >= 0 );
|
||||
if( !isSimilarKeypoints( validKeypoints[v], calcKeypoints[nearestIdx] ) )
|
||||
badPointCount++;
|
||||
}
|
||||
ts->printf( cvtest::TS::LOG, "badPointCount = %d; validPointCount = %d; calcPointCount = %d\n",
|
||||
badPointCount, validKeypoints.size(), calcKeypoints.size() );
|
||||
if( badPointCount > 0.9 * commonPointCount )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, " - Bad accuracy!\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
return;
|
||||
}
|
||||
ts->printf( cvtest::TS::LOG, " - OK\n" );
|
||||
}
|
||||
|
||||
void CV_FeatureDetectorTest::regressionTest()
|
||||
{
|
||||
assert( !fdetector.empty() );
|
||||
string imgFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + IMAGE_FILENAME;
|
||||
string resFilename = string(ts->get_data_path()) + DETECTOR_DIR + "/" + string(name) + ".xml.gz";
|
||||
|
||||
// Read the test image.
|
||||
Mat image = imread( imgFilename );
|
||||
if( image.empty() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Image %s can not be read.\n", imgFilename.c_str() );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
FileStorage fs( resFilename, FileStorage::READ );
|
||||
|
||||
// Compute keypoints.
|
||||
vector<KeyPoint> calcKeypoints;
|
||||
fdetector->detect( image, calcKeypoints );
|
||||
|
||||
if( fs.isOpened() ) // Compare computed and valid keypoints.
|
||||
{
|
||||
// TODO compare saved feature detector params with current ones
|
||||
|
||||
// Read validation keypoints set.
|
||||
vector<KeyPoint> validKeypoints;
|
||||
read( fs["keypoints"], validKeypoints );
|
||||
if( validKeypoints.empty() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Keypoints can not be read.\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
compareKeypointSets( validKeypoints, calcKeypoints );
|
||||
}
|
||||
else // Write detector parameters and computed keypoints as validation data.
|
||||
{
|
||||
fs.open( resFilename, FileStorage::WRITE );
|
||||
if( !fs.isOpened() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "File %s can not be opened to write.\n", resFilename.c_str() );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
fs << "detector_params" << "{";
|
||||
fdetector->write( fs );
|
||||
fs << "}";
|
||||
|
||||
write( fs, "keypoints", calcKeypoints );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CV_FeatureDetectorTest::run( int /*start_from*/ )
|
||||
{
|
||||
if( !fdetector )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Feature detector is empty.\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
emptyDataTest();
|
||||
regressionTest();
|
||||
|
||||
ts->set_failed_test_info( cvtest::TS::OK );
|
||||
}
|
||||
|
||||
}} // namespace
|
78
3rdparty/opencv-4.5.4/modules/features2d/test/test_drawing.cpp
vendored
Normal file
78
3rdparty/opencv-4.5.4/modules/features2d/test/test_drawing.cpp
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
// 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.
|
||||
//
|
||||
// Copyright (C) 2018, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
static
|
||||
Mat getReference_DrawKeypoint(int cn)
|
||||
{
|
||||
static Mat ref = (Mat_<uint8_t>(11, 11) <<
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 15, 54, 15, 1, 1, 1, 1,
|
||||
1, 1, 1, 76, 217, 217, 221, 81, 1, 1, 1,
|
||||
1, 1, 100, 224, 111, 57, 115, 225, 101, 1, 1,
|
||||
1, 44, 215, 100, 1, 1, 1, 101, 214, 44, 1,
|
||||
1, 54, 212, 57, 1, 1, 1, 55, 212, 55, 1,
|
||||
1, 40, 215, 104, 1, 1, 1, 105, 215, 40, 1,
|
||||
1, 1, 102, 221, 111, 55, 115, 222, 103, 1, 1,
|
||||
1, 1, 1, 76, 218, 217, 220, 81, 1, 1, 1,
|
||||
1, 1, 1, 1, 15, 55, 15, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
|
||||
Mat res;
|
||||
cvtColor(ref, res, (cn == 4) ? COLOR_GRAY2BGRA : COLOR_GRAY2BGR);
|
||||
return res;
|
||||
}
|
||||
|
||||
typedef testing::TestWithParam<MatType> Features2D_drawKeypoints;
|
||||
TEST_P(Features2D_drawKeypoints, Accuracy)
|
||||
{
|
||||
const int cn = CV_MAT_CN(GetParam());
|
||||
Mat inpImg(11, 11, GetParam(), Scalar(1, 1, 1, 255)), outImg;
|
||||
|
||||
std::vector<KeyPoint> keypoints(1, KeyPoint(5, 5, 1));
|
||||
drawKeypoints(inpImg, keypoints, outImg, Scalar::all(255));
|
||||
ASSERT_EQ(outImg.channels(), (cn == 4) ? 4 : 3);
|
||||
|
||||
Mat ref_ = getReference_DrawKeypoint(cn);
|
||||
EXPECT_EQ(0, cv::norm(outImg, ref_, NORM_INF));
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Features2D_drawKeypoints, Values(CV_8UC1, CV_8UC3, CV_8UC4));
|
||||
|
||||
typedef testing::TestWithParam<tuple<MatType, MatType> > Features2D_drawMatches;
|
||||
TEST_P(Features2D_drawMatches, Accuracy)
|
||||
{
|
||||
Mat inpImg1(11, 11, get<0>(GetParam()), Scalar(1, 1, 1, 255));
|
||||
Mat inpImg2(11, 11, get<1>(GetParam()), Scalar(2, 2, 2, 255)), outImg2, outImg;
|
||||
|
||||
std::vector<KeyPoint> keypoints(1, KeyPoint(5, 5, 1));
|
||||
|
||||
// Get outImg2 using drawKeypoints assuming that it works correctly (see the test above).
|
||||
drawKeypoints(inpImg2, keypoints, outImg2, Scalar::all(255));
|
||||
ASSERT_EQ(outImg2.channels(), (inpImg2.channels() == 4) ? 4 : 3);
|
||||
|
||||
// Merge both references.
|
||||
const int cn = max(3, max(inpImg1.channels(), inpImg2.channels()));
|
||||
if (cn == 4 && outImg2.channels() == 3)
|
||||
cvtColor(outImg2, outImg2, COLOR_BGR2BGRA);
|
||||
Mat ref_ = getReference_DrawKeypoint(cn);
|
||||
Mat concattedRef;
|
||||
hconcat(ref_, outImg2, concattedRef);
|
||||
|
||||
std::vector<DMatch> matches;
|
||||
drawMatches(inpImg1, keypoints, inpImg2, keypoints, matches, outImg,
|
||||
Scalar::all(255), Scalar::all(255));
|
||||
ASSERT_EQ(outImg.channels(), cn);
|
||||
|
||||
EXPECT_EQ(0, cv::norm(outImg, concattedRef, NORM_INF));
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(/**/, Features2D_drawMatches, Combine(
|
||||
Values(CV_8UC1, CV_8UC3, CV_8UC4),
|
||||
Values(CV_8UC1, CV_8UC3, CV_8UC4)
|
||||
));
|
||||
|
||||
}} // namespace
|
138
3rdparty/opencv-4.5.4/modules/features2d/test/test_fast.cpp
vendored
Normal file
138
3rdparty/opencv-4.5.4/modules/features2d/test/test_fast.cpp
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
/*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) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
class CV_FastTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_FastTest();
|
||||
~CV_FastTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
CV_FastTest::CV_FastTest() {}
|
||||
CV_FastTest::~CV_FastTest() {}
|
||||
|
||||
void CV_FastTest::run( int )
|
||||
{
|
||||
for(int type=0; type <= 2; ++type) {
|
||||
Mat image1 = imread(string(ts->get_data_path()) + "inpaint/orig.png");
|
||||
Mat image2 = imread(string(ts->get_data_path()) + "cameracalibration/chess9.png");
|
||||
string xml = string(ts->get_data_path()) + format("fast/result%d.xml", type);
|
||||
|
||||
if (image1.empty() || image2.empty())
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
Mat gray1, gray2;
|
||||
cvtColor(image1, gray1, COLOR_BGR2GRAY);
|
||||
cvtColor(image2, gray2, COLOR_BGR2GRAY);
|
||||
|
||||
vector<KeyPoint> keypoints1;
|
||||
vector<KeyPoint> keypoints2;
|
||||
FAST(gray1, keypoints1, 30, true, static_cast<FastFeatureDetector::DetectorType>(type));
|
||||
FAST(gray2, keypoints2, (type > 0 ? 30 : 20), true, static_cast<FastFeatureDetector::DetectorType>(type));
|
||||
|
||||
for(size_t i = 0; i < keypoints1.size(); ++i)
|
||||
{
|
||||
const KeyPoint& kp = keypoints1[i];
|
||||
cv::circle(image1, kp.pt, cvRound(kp.size/2), Scalar(255, 0, 0));
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < keypoints2.size(); ++i)
|
||||
{
|
||||
const KeyPoint& kp = keypoints2[i];
|
||||
cv::circle(image2, kp.pt, cvRound(kp.size/2), Scalar(255, 0, 0));
|
||||
}
|
||||
|
||||
Mat kps1(1, (int)(keypoints1.size() * sizeof(KeyPoint)), CV_8U, &keypoints1[0]);
|
||||
Mat kps2(1, (int)(keypoints2.size() * sizeof(KeyPoint)), CV_8U, &keypoints2[0]);
|
||||
|
||||
FileStorage fs(xml, FileStorage::READ);
|
||||
if (!fs.isOpened())
|
||||
{
|
||||
fs.open(xml, FileStorage::WRITE);
|
||||
if (!fs.isOpened())
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
return;
|
||||
}
|
||||
fs << "exp_kps1" << kps1;
|
||||
fs << "exp_kps2" << kps2;
|
||||
fs.release();
|
||||
fs.open(xml, FileStorage::READ);
|
||||
if (!fs.isOpened())
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Mat exp_kps1, exp_kps2;
|
||||
read( fs["exp_kps1"], exp_kps1, Mat() );
|
||||
read( fs["exp_kps2"], exp_kps2, Mat() );
|
||||
fs.release();
|
||||
|
||||
if ( exp_kps1.size != kps1.size || 0 != cvtest::norm(exp_kps1, kps1, NORM_L2) ||
|
||||
exp_kps2.size != kps2.size || 0 != cvtest::norm(exp_kps2, kps2, NORM_L2))
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return;
|
||||
}
|
||||
|
||||
/*cv::namedWindow("Img1"); cv::imshow("Img1", image1);
|
||||
cv::namedWindow("Img2"); cv::imshow("Img2", image2);
|
||||
cv::waitKey(0);*/
|
||||
}
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Features2d_FAST, regression) { CV_FastTest test; test.safe_run(); }
|
||||
|
||||
}} // namespace
|
85
3rdparty/opencv-4.5.4/modules/features2d/test/test_invariance_utils.hpp
vendored
Normal file
85
3rdparty/opencv-4.5.4/modules/features2d/test/test_invariance_utils.hpp
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
// 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
|
||||
|
||||
#ifndef __OPENCV_TEST_INVARIANCE_UTILS_HPP__
|
||||
#define __OPENCV_TEST_INVARIANCE_UTILS_HPP__
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
Mat generateHomography(float angle)
|
||||
{
|
||||
// angle - rotation around Oz in degrees
|
||||
float angleRadian = static_cast<float>(angle * CV_PI / 180);
|
||||
Mat H = Mat::eye(3, 3, CV_32FC1);
|
||||
H.at<float>(0,0) = H.at<float>(1,1) = std::cos(angleRadian);
|
||||
H.at<float>(0,1) = -std::sin(angleRadian);
|
||||
H.at<float>(1,0) = std::sin(angleRadian);
|
||||
|
||||
return H;
|
||||
}
|
||||
|
||||
Mat rotateImage(const Mat& srcImage, const Mat& srcMask, float angle, Mat& dstImage, Mat& dstMask)
|
||||
{
|
||||
// angle - rotation around Oz in degrees
|
||||
float diag = std::sqrt(static_cast<float>(srcImage.cols * srcImage.cols + srcImage.rows * srcImage.rows));
|
||||
Mat LUShift = Mat::eye(3, 3, CV_32FC1); // left up
|
||||
LUShift.at<float>(0,2) = static_cast<float>(-srcImage.cols/2);
|
||||
LUShift.at<float>(1,2) = static_cast<float>(-srcImage.rows/2);
|
||||
Mat RDShift = Mat::eye(3, 3, CV_32FC1); // right down
|
||||
RDShift.at<float>(0,2) = diag/2;
|
||||
RDShift.at<float>(1,2) = diag/2;
|
||||
Size sz(cvRound(diag), cvRound(diag));
|
||||
|
||||
Mat H = RDShift * generateHomography(angle) * LUShift;
|
||||
warpPerspective(srcImage, dstImage, H, sz);
|
||||
warpPerspective(srcMask, dstMask, H, sz);
|
||||
|
||||
return H;
|
||||
}
|
||||
|
||||
float calcCirclesIntersectArea(const Point2f& p0, float r0, const Point2f& p1, float r1)
|
||||
{
|
||||
float c = static_cast<float>(cv::norm(p0 - p1)), sqr_c = c * c;
|
||||
|
||||
float sqr_r0 = r0 * r0;
|
||||
float sqr_r1 = r1 * r1;
|
||||
|
||||
if(r0 + r1 <= c)
|
||||
return 0;
|
||||
|
||||
float minR = std::min(r0, r1);
|
||||
float maxR = std::max(r0, r1);
|
||||
if(c + minR <= maxR)
|
||||
return static_cast<float>(CV_PI * minR * minR);
|
||||
|
||||
float cos_halfA0 = (sqr_r0 + sqr_c - sqr_r1) / (2 * r0 * c);
|
||||
float cos_halfA1 = (sqr_r1 + sqr_c - sqr_r0) / (2 * r1 * c);
|
||||
|
||||
float A0 = 2 * acos(cos_halfA0);
|
||||
float A1 = 2 * acos(cos_halfA1);
|
||||
|
||||
return 0.5f * sqr_r0 * (A0 - sin(A0)) +
|
||||
0.5f * sqr_r1 * (A1 - sin(A1));
|
||||
}
|
||||
|
||||
float calcIntersectRatio(const Point2f& p0, float r0, const Point2f& p1, float r1)
|
||||
{
|
||||
float intersectArea = calcCirclesIntersectArea(p0, r0, p1, r1);
|
||||
float unionArea = static_cast<float>(CV_PI) * (r0 * r0 + r1 * r1) - intersectArea;
|
||||
return intersectArea / unionArea;
|
||||
}
|
||||
|
||||
void scaleKeyPoints(const vector<KeyPoint>& src, vector<KeyPoint>& dst, float scale)
|
||||
{
|
||||
dst.resize(src.size());
|
||||
for (size_t i = 0; i < src.size(); i++) {
|
||||
dst[i] = src[i];
|
||||
dst[i].pt.x *= scale;
|
||||
dst[i].pt.y *= scale;
|
||||
dst[i].size *= scale;
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
#endif // __OPENCV_TEST_INVARIANCE_UTILS_HPP__
|
187
3rdparty/opencv-4.5.4/modules/features2d/test/test_keypoints.cpp
vendored
Normal file
187
3rdparty/opencv-4.5.4/modules/features2d/test/test_keypoints.cpp
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
/*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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include "opencv2/core/core_c.h"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
const string FEATURES2D_DIR = "features2d";
|
||||
const string IMAGE_FILENAME = "tsukuba.png";
|
||||
|
||||
/****************************************************************************************\
|
||||
* Test for KeyPoint *
|
||||
\****************************************************************************************/
|
||||
|
||||
class CV_FeatureDetectorKeypointsTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_FeatureDetectorKeypointsTest(const Ptr<FeatureDetector>& _detector) :
|
||||
detector(_detector) {}
|
||||
|
||||
protected:
|
||||
virtual void run(int)
|
||||
{
|
||||
CV_Assert(detector);
|
||||
string imgFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + IMAGE_FILENAME;
|
||||
|
||||
// Read the test image.
|
||||
Mat image = imread(imgFilename);
|
||||
if(image.empty())
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "Image %s can not be read.\n", imgFilename.c_str());
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
return;
|
||||
}
|
||||
|
||||
vector<KeyPoint> keypoints;
|
||||
detector->detect(image, keypoints);
|
||||
|
||||
if(keypoints.empty())
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "Detector can't find keypoints in image.\n");
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
|
||||
return;
|
||||
}
|
||||
|
||||
Rect r(0, 0, image.cols, image.rows);
|
||||
for(size_t i = 0; i < keypoints.size(); i++)
|
||||
{
|
||||
const KeyPoint& kp = keypoints[i];
|
||||
|
||||
if(!r.contains(kp.pt))
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "KeyPoint::pt is out of image (x=%f, y=%f).\n", kp.pt.x, kp.pt.y);
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
|
||||
return;
|
||||
}
|
||||
|
||||
if(kp.size <= 0.f)
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "KeyPoint::size is not positive (%f).\n", kp.size);
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
|
||||
return;
|
||||
}
|
||||
|
||||
if((kp.angle < 0.f && kp.angle != -1.f) || kp.angle >= 360.f)
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "KeyPoint::angle is out of range [0, 360). It's %f.\n", kp.angle);
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
Ptr<FeatureDetector> detector;
|
||||
};
|
||||
|
||||
|
||||
// Registration of tests
|
||||
|
||||
TEST(Features2d_Detector_Keypoints_BRISK, validation)
|
||||
{
|
||||
CV_FeatureDetectorKeypointsTest test(BRISK::create());
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST(Features2d_Detector_Keypoints_FAST, validation)
|
||||
{
|
||||
CV_FeatureDetectorKeypointsTest test(FastFeatureDetector::create());
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST(Features2d_Detector_Keypoints_AGAST, validation)
|
||||
{
|
||||
CV_FeatureDetectorKeypointsTest test(AgastFeatureDetector::create());
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST(Features2d_Detector_Keypoints_HARRIS, validation)
|
||||
{
|
||||
|
||||
CV_FeatureDetectorKeypointsTest test(GFTTDetector::create(1000, 0.01, 1, 3, 3, true, 0.04));
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST(Features2d_Detector_Keypoints_GFTT, validation)
|
||||
{
|
||||
Ptr<GFTTDetector> gftt = GFTTDetector::create();
|
||||
gftt->setHarrisDetector(true);
|
||||
CV_FeatureDetectorKeypointsTest test(gftt);
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST(Features2d_Detector_Keypoints_MSER, validation)
|
||||
{
|
||||
CV_FeatureDetectorKeypointsTest test(MSER::create());
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST(Features2d_Detector_Keypoints_ORB, validation)
|
||||
{
|
||||
CV_FeatureDetectorKeypointsTest test(ORB::create());
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST(Features2d_Detector_Keypoints_KAZE, validation)
|
||||
{
|
||||
CV_FeatureDetectorKeypointsTest test(KAZE::create());
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
TEST(Features2d_Detector_Keypoints_AKAZE, validation)
|
||||
{
|
||||
CV_FeatureDetectorKeypointsTest test_kaze(AKAZE::create(AKAZE::DESCRIPTOR_KAZE));
|
||||
test_kaze.safe_run();
|
||||
|
||||
CV_FeatureDetectorKeypointsTest test_mldb(AKAZE::create(AKAZE::DESCRIPTOR_MLDB));
|
||||
test_mldb.safe_run();
|
||||
}
|
||||
|
||||
TEST(Features2d_Detector_Keypoints_SIFT, validation)
|
||||
{
|
||||
CV_FeatureDetectorKeypointsTest test(SIFT::create());
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
|
||||
}} // namespace
|
10
3rdparty/opencv-4.5.4/modules/features2d/test/test_main.cpp
vendored
Normal file
10
3rdparty/opencv-4.5.4/modules/features2d/test/test_main.cpp
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
// 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"
|
||||
|
||||
#if defined(HAVE_HPX)
|
||||
#include <hpx/hpx_main.hpp>
|
||||
#endif
|
||||
|
||||
CV_TEST_MAIN("cv")
|
635
3rdparty/opencv-4.5.4/modules/features2d/test/test_matchers_algorithmic.cpp
vendored
Normal file
635
3rdparty/opencv-4.5.4/modules/features2d/test/test_matchers_algorithmic.cpp
vendored
Normal file
@ -0,0 +1,635 @@
|
||||
/*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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
const string FEATURES2D_DIR = "features2d";
|
||||
const string IMAGE_FILENAME = "tsukuba.png";
|
||||
|
||||
/****************************************************************************************\
|
||||
* Algorithmic tests for descriptor matchers *
|
||||
\****************************************************************************************/
|
||||
class CV_DescriptorMatcherTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_DescriptorMatcherTest( const string& _name, const Ptr<DescriptorMatcher>& _dmatcher, float _badPart ) :
|
||||
badPart(_badPart), name(_name), dmatcher(_dmatcher)
|
||||
{}
|
||||
protected:
|
||||
static const int dim = 500;
|
||||
static const int queryDescCount = 300; // must be even number because we split train data in some cases in two
|
||||
static const int countFactor = 4; // do not change it
|
||||
const float badPart;
|
||||
|
||||
virtual void run( int );
|
||||
void generateData( Mat& query, Mat& train );
|
||||
|
||||
#if 0
|
||||
void emptyDataTest(); // FIXIT not used
|
||||
#endif
|
||||
void matchTest( const Mat& query, const Mat& train );
|
||||
void knnMatchTest( const Mat& query, const Mat& train );
|
||||
void radiusMatchTest( const Mat& query, const Mat& train );
|
||||
|
||||
string name;
|
||||
Ptr<DescriptorMatcher> dmatcher;
|
||||
|
||||
private:
|
||||
CV_DescriptorMatcherTest& operator=(const CV_DescriptorMatcherTest&) { return *this; }
|
||||
};
|
||||
|
||||
#if 0
|
||||
void CV_DescriptorMatcherTest::emptyDataTest()
|
||||
{
|
||||
assert( !dmatcher.empty() );
|
||||
Mat queryDescriptors, trainDescriptors, mask;
|
||||
vector<Mat> trainDescriptorCollection, masks;
|
||||
vector<DMatch> matches;
|
||||
vector<vector<DMatch> > vmatches;
|
||||
|
||||
try
|
||||
{
|
||||
dmatcher->match( queryDescriptors, trainDescriptors, matches, mask );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "match() on empty descriptors must not generate exception (1).\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
dmatcher->knnMatch( queryDescriptors, trainDescriptors, vmatches, 2, mask );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "knnMatch() on empty descriptors must not generate exception (1).\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
dmatcher->radiusMatch( queryDescriptors, trainDescriptors, vmatches, 10.f, mask );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "radiusMatch() on empty descriptors must not generate exception (1).\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
dmatcher->add( trainDescriptorCollection );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "add() on empty descriptors must not generate exception.\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
dmatcher->match( queryDescriptors, matches, masks );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "match() on empty descriptors must not generate exception (2).\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
dmatcher->knnMatch( queryDescriptors, vmatches, 2, masks );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "knnMatch() on empty descriptors must not generate exception (2).\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
dmatcher->radiusMatch( queryDescriptors, vmatches, 10.f, masks );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "radiusMatch() on empty descriptors must not generate exception (2).\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void CV_DescriptorMatcherTest::generateData( Mat& query, Mat& train )
|
||||
{
|
||||
RNG& rng = theRNG();
|
||||
|
||||
// Generate query descriptors randomly.
|
||||
// Descriptor vector elements are integer values.
|
||||
Mat buf( queryDescCount, dim, CV_32SC1 );
|
||||
rng.fill( buf, RNG::UNIFORM, Scalar::all(0), Scalar(3) );
|
||||
buf.convertTo( query, CV_32FC1 );
|
||||
|
||||
// Generate train descriptors as follows:
|
||||
// copy each query descriptor to train set countFactor times
|
||||
// and perturb some one element of the copied descriptors in
|
||||
// in ascending order. General boundaries of the perturbation
|
||||
// are (0.f, 1.f).
|
||||
train.create( query.rows*countFactor, query.cols, CV_32FC1 );
|
||||
float step = 1.f / countFactor;
|
||||
for( int qIdx = 0; qIdx < query.rows; qIdx++ )
|
||||
{
|
||||
Mat queryDescriptor = query.row(qIdx);
|
||||
for( int c = 0; c < countFactor; c++ )
|
||||
{
|
||||
int tIdx = qIdx * countFactor + c;
|
||||
Mat trainDescriptor = train.row(tIdx);
|
||||
queryDescriptor.copyTo( trainDescriptor );
|
||||
int elem = rng(dim);
|
||||
float diff = rng.uniform( step*c, step*(c+1) );
|
||||
trainDescriptor.at<float>(0, elem) += diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CV_DescriptorMatcherTest::matchTest( const Mat& query, const Mat& train )
|
||||
{
|
||||
dmatcher->clear();
|
||||
|
||||
// test const version of match()
|
||||
{
|
||||
vector<DMatch> matches;
|
||||
dmatcher->match( query, train, matches );
|
||||
|
||||
if( (int)matches.size() != queryDescCount )
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "Incorrect matches count while test match() function (1).\n");
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
else
|
||||
{
|
||||
int badCount = 0;
|
||||
for( size_t i = 0; i < matches.size(); i++ )
|
||||
{
|
||||
DMatch& match = matches[i];
|
||||
if( (match.queryIdx != (int)i) || (match.trainIdx != (int)i*countFactor) || (match.imgIdx != 0) )
|
||||
badCount++;
|
||||
}
|
||||
if( (float)badCount > (float)queryDescCount*badPart )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "%f - too large bad matches part while test match() function (1).\n",
|
||||
(float)badCount/(float)queryDescCount );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test const version of match() for the same query and test descriptors
|
||||
{
|
||||
vector<DMatch> matches;
|
||||
dmatcher->match( query, query, matches );
|
||||
|
||||
if( (int)matches.size() != query.rows )
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "Incorrect matches count while test match() function for the same query and test descriptors (1).\n");
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( size_t i = 0; i < matches.size(); i++ )
|
||||
{
|
||||
DMatch& match = matches[i];
|
||||
//std::cout << match.distance << std::endl;
|
||||
|
||||
if( match.queryIdx != (int)i || match.trainIdx != (int)i || std::abs(match.distance) > FLT_EPSILON )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Bad match (i=%d, queryIdx=%d, trainIdx=%d, distance=%f) while test match() function for the same query and test descriptors (1).\n",
|
||||
i, match.queryIdx, match.trainIdx, match.distance );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test version of match() with add()
|
||||
{
|
||||
vector<DMatch> matches;
|
||||
// make add() twice to test such case
|
||||
dmatcher->add( vector<Mat>(1,train.rowRange(0, train.rows/2)) );
|
||||
dmatcher->add( vector<Mat>(1,train.rowRange(train.rows/2, train.rows)) );
|
||||
// prepare masks (make first nearest match illegal)
|
||||
vector<Mat> masks(2);
|
||||
for(int mi = 0; mi < 2; mi++ )
|
||||
{
|
||||
masks[mi] = Mat(query.rows, train.rows/2, CV_8UC1, Scalar::all(1));
|
||||
for( int di = 0; di < queryDescCount/2; di++ )
|
||||
masks[mi].col(di*countFactor).setTo(Scalar::all(0));
|
||||
}
|
||||
|
||||
dmatcher->match( query, matches, masks );
|
||||
|
||||
if( (int)matches.size() != queryDescCount )
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "Incorrect matches count while test match() function (2).\n");
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
else
|
||||
{
|
||||
int badCount = 0;
|
||||
for( size_t i = 0; i < matches.size(); i++ )
|
||||
{
|
||||
DMatch& match = matches[i];
|
||||
int shift = dmatcher->isMaskSupported() ? 1 : 0;
|
||||
{
|
||||
if( i < queryDescCount/2 )
|
||||
{
|
||||
if( (match.queryIdx != (int)i) || (match.trainIdx != (int)i*countFactor + shift) || (match.imgIdx != 0) )
|
||||
badCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (match.queryIdx != (int)i) || (match.trainIdx != ((int)i-queryDescCount/2)*countFactor + shift) || (match.imgIdx != 1) )
|
||||
badCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( (float)badCount > (float)queryDescCount*badPart )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "%f - too large bad matches part while test match() function (2).\n",
|
||||
(float)badCount/(float)queryDescCount );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CV_DescriptorMatcherTest::knnMatchTest( const Mat& query, const Mat& train )
|
||||
{
|
||||
dmatcher->clear();
|
||||
|
||||
// test const version of knnMatch()
|
||||
{
|
||||
const int knn = 3;
|
||||
|
||||
vector<vector<DMatch> > matches;
|
||||
dmatcher->knnMatch( query, train, matches, knn );
|
||||
|
||||
if( (int)matches.size() != queryDescCount )
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "Incorrect matches count while test knnMatch() function (1).\n");
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
else
|
||||
{
|
||||
int badCount = 0;
|
||||
for( size_t i = 0; i < matches.size(); i++ )
|
||||
{
|
||||
if( (int)matches[i].size() != knn )
|
||||
badCount++;
|
||||
else
|
||||
{
|
||||
int localBadCount = 0;
|
||||
for( int k = 0; k < knn; k++ )
|
||||
{
|
||||
DMatch& match = matches[i][k];
|
||||
if( (match.queryIdx != (int)i) || (match.trainIdx != (int)i*countFactor+k) || (match.imgIdx != 0) )
|
||||
localBadCount++;
|
||||
}
|
||||
badCount += localBadCount > 0 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
if( (float)badCount > (float)queryDescCount*badPart )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "%f - too large bad matches part while test knnMatch() function (1).\n",
|
||||
(float)badCount/(float)queryDescCount );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test version of knnMatch() with add()
|
||||
{
|
||||
const int knn = 2;
|
||||
vector<vector<DMatch> > matches;
|
||||
// make add() twice to test such case
|
||||
dmatcher->add( vector<Mat>(1,train.rowRange(0, train.rows/2)) );
|
||||
dmatcher->add( vector<Mat>(1,train.rowRange(train.rows/2, train.rows)) );
|
||||
// prepare masks (make first nearest match illegal)
|
||||
vector<Mat> masks(2);
|
||||
for(int mi = 0; mi < 2; mi++ )
|
||||
{
|
||||
masks[mi] = Mat(query.rows, train.rows/2, CV_8UC1, Scalar::all(1));
|
||||
for( int di = 0; di < queryDescCount/2; di++ )
|
||||
masks[mi].col(di*countFactor).setTo(Scalar::all(0));
|
||||
}
|
||||
|
||||
dmatcher->knnMatch( query, matches, knn, masks );
|
||||
|
||||
if( (int)matches.size() != queryDescCount )
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "Incorrect matches count while test knnMatch() function (2).\n");
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
else
|
||||
{
|
||||
int badCount = 0;
|
||||
int shift = dmatcher->isMaskSupported() ? 1 : 0;
|
||||
for( size_t i = 0; i < matches.size(); i++ )
|
||||
{
|
||||
if( (int)matches[i].size() != knn )
|
||||
badCount++;
|
||||
else
|
||||
{
|
||||
int localBadCount = 0;
|
||||
for( int k = 0; k < knn; k++ )
|
||||
{
|
||||
DMatch& match = matches[i][k];
|
||||
{
|
||||
if( i < queryDescCount/2 )
|
||||
{
|
||||
if( (match.queryIdx != (int)i) || (match.trainIdx != (int)i*countFactor + k + shift) ||
|
||||
(match.imgIdx != 0) )
|
||||
localBadCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (match.queryIdx != (int)i) || (match.trainIdx != ((int)i-queryDescCount/2)*countFactor + k + shift) ||
|
||||
(match.imgIdx != 1) )
|
||||
localBadCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
badCount += localBadCount > 0 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
if( (float)badCount > (float)queryDescCount*badPart )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "%f - too large bad matches part while test knnMatch() function (2).\n",
|
||||
(float)badCount/(float)queryDescCount );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CV_DescriptorMatcherTest::radiusMatchTest( const Mat& query, const Mat& train )
|
||||
{
|
||||
dmatcher->clear();
|
||||
// test const version of match()
|
||||
{
|
||||
const float radius = 1.f/countFactor;
|
||||
vector<vector<DMatch> > matches;
|
||||
dmatcher->radiusMatch( query, train, matches, radius );
|
||||
|
||||
if( (int)matches.size() != queryDescCount )
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "Incorrect matches count while test radiusMatch() function (1).\n");
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
else
|
||||
{
|
||||
int badCount = 0;
|
||||
for( size_t i = 0; i < matches.size(); i++ )
|
||||
{
|
||||
if( (int)matches[i].size() != 1 )
|
||||
badCount++;
|
||||
else
|
||||
{
|
||||
DMatch& match = matches[i][0];
|
||||
if( (match.queryIdx != (int)i) || (match.trainIdx != (int)i*countFactor) || (match.imgIdx != 0) )
|
||||
badCount++;
|
||||
}
|
||||
}
|
||||
if( (float)badCount > (float)queryDescCount*badPart )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "%f - too large bad matches part while test radiusMatch() function (1).\n",
|
||||
(float)badCount/(float)queryDescCount );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test version of match() with add()
|
||||
{
|
||||
int n = 3;
|
||||
const float radius = 1.f/countFactor * n;
|
||||
vector<vector<DMatch> > matches;
|
||||
// make add() twice to test such case
|
||||
dmatcher->add( vector<Mat>(1,train.rowRange(0, train.rows/2)) );
|
||||
dmatcher->add( vector<Mat>(1,train.rowRange(train.rows/2, train.rows)) );
|
||||
// prepare masks (make first nearest match illegal)
|
||||
vector<Mat> masks(2);
|
||||
for(int mi = 0; mi < 2; mi++ )
|
||||
{
|
||||
masks[mi] = Mat(query.rows, train.rows/2, CV_8UC1, Scalar::all(1));
|
||||
for( int di = 0; di < queryDescCount/2; di++ )
|
||||
masks[mi].col(di*countFactor).setTo(Scalar::all(0));
|
||||
}
|
||||
|
||||
dmatcher->radiusMatch( query, matches, radius, masks );
|
||||
|
||||
//int curRes = cvtest::TS::OK;
|
||||
if( (int)matches.size() != queryDescCount )
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "Incorrect matches count while test radiusMatch() function (1).\n");
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
}
|
||||
|
||||
int badCount = 0;
|
||||
int shift = dmatcher->isMaskSupported() ? 1 : 0;
|
||||
int needMatchCount = dmatcher->isMaskSupported() ? n-1 : n;
|
||||
for( size_t i = 0; i < matches.size(); i++ )
|
||||
{
|
||||
if( (int)matches[i].size() != needMatchCount )
|
||||
badCount++;
|
||||
else
|
||||
{
|
||||
int localBadCount = 0;
|
||||
for( int k = 0; k < needMatchCount; k++ )
|
||||
{
|
||||
DMatch& match = matches[i][k];
|
||||
{
|
||||
if( i < queryDescCount/2 )
|
||||
{
|
||||
if( (match.queryIdx != (int)i) || (match.trainIdx != (int)i*countFactor + k + shift) ||
|
||||
(match.imgIdx != 0) )
|
||||
localBadCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (match.queryIdx != (int)i) || (match.trainIdx != ((int)i-queryDescCount/2)*countFactor + k + shift) ||
|
||||
(match.imgIdx != 1) )
|
||||
localBadCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
badCount += localBadCount > 0 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
if( (float)badCount > (float)queryDescCount*badPart )
|
||||
{
|
||||
//curRes = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
ts->printf( cvtest::TS::LOG, "%f - too large bad matches part while test radiusMatch() function (2).\n",
|
||||
(float)badCount/(float)queryDescCount );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CV_DescriptorMatcherTest::run( int )
|
||||
{
|
||||
Mat query, train;
|
||||
generateData( query, train );
|
||||
|
||||
matchTest( query, train );
|
||||
|
||||
knnMatchTest( query, train );
|
||||
|
||||
radiusMatchTest( query, train );
|
||||
}
|
||||
|
||||
/****************************************************************************************\
|
||||
* Tests registrations *
|
||||
\****************************************************************************************/
|
||||
|
||||
TEST( Features2d_DescriptorMatcher_BruteForce, regression )
|
||||
{
|
||||
CV_DescriptorMatcherTest test( "descriptor-matcher-brute-force",
|
||||
DescriptorMatcher::create("BruteForce"), 0.01f );
|
||||
test.safe_run();
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCV_FLANN
|
||||
TEST( Features2d_DescriptorMatcher_FlannBased, regression )
|
||||
{
|
||||
CV_DescriptorMatcherTest test( "descriptor-matcher-flann-based",
|
||||
DescriptorMatcher::create("FlannBased"), 0.04f );
|
||||
test.safe_run();
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST( Features2d_DMatch, read_write )
|
||||
{
|
||||
FileStorage fs(".xml", FileStorage::WRITE + FileStorage::MEMORY);
|
||||
vector<DMatch> matches;
|
||||
matches.push_back(DMatch(1,2,3,4.5f));
|
||||
fs << "Match" << matches;
|
||||
String str = fs.releaseAndGetString();
|
||||
ASSERT_NE( strstr(str.c_str(), "4.5"), (char*)0 );
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCV_FLANN
|
||||
TEST( Features2d_FlannBasedMatcher, read_write )
|
||||
{
|
||||
static const char* ymlfile = "%YAML:1.0\n---\n"
|
||||
"format: 3\n"
|
||||
"indexParams:\n"
|
||||
" -\n"
|
||||
" name: algorithm\n"
|
||||
" type: 9\n" // FLANN_INDEX_TYPE_ALGORITHM
|
||||
" value: 6\n"// this line is changed!
|
||||
" -\n"
|
||||
" name: trees\n"
|
||||
" type: 4\n"
|
||||
" value: 4\n"
|
||||
"searchParams:\n"
|
||||
" -\n"
|
||||
" name: checks\n"
|
||||
" type: 4\n"
|
||||
" value: 32\n"
|
||||
" -\n"
|
||||
" name: eps\n"
|
||||
" type: 5\n"
|
||||
" value: 4.\n"// this line is changed!
|
||||
" -\n"
|
||||
" name: explore_all_trees\n"
|
||||
" type: 8\n"
|
||||
" value: 0\n"
|
||||
" -\n"
|
||||
" name: sorted\n"
|
||||
" type: 8\n" // FLANN_INDEX_TYPE_BOOL
|
||||
" value: 1\n";
|
||||
|
||||
Ptr<DescriptorMatcher> matcher = FlannBasedMatcher::create();
|
||||
FileStorage fs_in(ymlfile, FileStorage::READ + FileStorage::MEMORY);
|
||||
matcher->read(fs_in.root());
|
||||
FileStorage fs_out(".yml", FileStorage::WRITE + FileStorage::MEMORY);
|
||||
matcher->write(fs_out);
|
||||
std::string out = fs_out.releaseAndGetString();
|
||||
|
||||
EXPECT_EQ(ymlfile, out);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(Features2d_DMatch, issue_11855)
|
||||
{
|
||||
Mat sources = (Mat_<uchar>(2, 3) << 1, 1, 0,
|
||||
1, 1, 1);
|
||||
Mat targets = (Mat_<uchar>(2, 3) << 1, 1, 1,
|
||||
0, 0, 0);
|
||||
Ptr<BFMatcher> bf = BFMatcher::create(NORM_HAMMING, true);
|
||||
vector<vector<DMatch> > match;
|
||||
bf->knnMatch(sources, targets, match, 1, noArray(), true);
|
||||
|
||||
ASSERT_EQ((size_t)1, match.size());
|
||||
ASSERT_EQ((size_t)1, match[0].size());
|
||||
EXPECT_EQ(1, match[0][0].queryIdx);
|
||||
EXPECT_EQ(0, match[0][0].trainIdx);
|
||||
EXPECT_EQ(0.0f, match[0][0].distance);
|
||||
}
|
||||
|
||||
TEST(Features2d_DMatch, issue_17771)
|
||||
{
|
||||
Mat sources = (Mat_<uchar>(2, 3) << 1, 1, 0,
|
||||
1, 1, 1);
|
||||
Mat targets = (Mat_<uchar>(2, 3) << 1, 1, 1,
|
||||
0, 0, 0);
|
||||
UMat usources = sources.getUMat(ACCESS_READ);
|
||||
UMat utargets = targets.getUMat(ACCESS_READ);
|
||||
vector<vector<DMatch> > match;
|
||||
Ptr<BFMatcher> ubf = BFMatcher::create(NORM_HAMMING);
|
||||
Mat mask = (Mat_<uchar>(2, 2) << 1, 0, 0, 1);
|
||||
EXPECT_NO_THROW(ubf->knnMatch(usources, utargets, match, 1, mask, true));
|
||||
}
|
||||
|
||||
}} // namespace
|
182
3rdparty/opencv-4.5.4/modules/features2d/test/test_mser.cpp
vendored
Normal file
182
3rdparty/opencv-4.5.4/modules/features2d/test/test_mser.cpp
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
/*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) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
#undef RENDER_MSERS
|
||||
#define RENDER_MSERS 0
|
||||
|
||||
#if defined RENDER_MSERS && RENDER_MSERS
|
||||
static void renderMSERs(const Mat& gray, Mat& img, const vector<vector<Point> >& msers)
|
||||
{
|
||||
cvtColor(gray, img, COLOR_GRAY2BGR);
|
||||
RNG rng((uint64)1749583);
|
||||
for( int i = 0; i < (int)msers.size(); i++ )
|
||||
{
|
||||
uchar b = rng.uniform(0, 256);
|
||||
uchar g = rng.uniform(0, 256);
|
||||
uchar r = rng.uniform(0, 256);
|
||||
Vec3b color(b, g, r);
|
||||
|
||||
const Point* pt = &msers[i][0];
|
||||
size_t j, n = msers[i].size();
|
||||
for( j = 0; j < n; j++ )
|
||||
img.at<Vec3b>(pt[j]) = color;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(Features2d_MSER, cases)
|
||||
{
|
||||
uchar buf[] =
|
||||
{
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
|
||||
};
|
||||
Mat big_image = imread(cvtest::TS::ptr()->get_data_path() + "mser/puzzle.png", 0);
|
||||
Mat small_image(14, 26, CV_8U, buf);
|
||||
static const int thresharr[] = { 0, 70, 120, 180, 255 };
|
||||
|
||||
const int kDelta = 5;
|
||||
Ptr<MSER> mserExtractor = MSER::create( kDelta );
|
||||
vector<vector<Point> > msers;
|
||||
vector<Rect> boxes;
|
||||
|
||||
RNG rng((uint64)123456);
|
||||
|
||||
for( int i = 0; i < 100; i++ )
|
||||
{
|
||||
bool use_big_image = rng.uniform(0, 7) != 0;
|
||||
bool invert = rng.uniform(0, 2) != 0;
|
||||
bool binarize = use_big_image ? rng.uniform(0, 5) != 0 : false;
|
||||
bool blur = rng.uniform(0, 2) != 0;
|
||||
int thresh = thresharr[rng.uniform(0, 5)];
|
||||
|
||||
/*if( i == 0 )
|
||||
{
|
||||
use_big_image = true;
|
||||
invert = binarize = blur = false;
|
||||
}*/
|
||||
|
||||
const Mat& src0 = use_big_image ? big_image : small_image;
|
||||
Mat src = src0.clone();
|
||||
|
||||
int kMinArea = use_big_image ? 256 : 10;
|
||||
int kMaxArea = (int)src.total()/4;
|
||||
|
||||
mserExtractor->setMinArea(kMinArea);
|
||||
mserExtractor->setMaxArea(kMaxArea);
|
||||
|
||||
if( invert )
|
||||
bitwise_not(src, src);
|
||||
if( binarize )
|
||||
cv::threshold(src, src, thresh, 255, THRESH_BINARY);
|
||||
if( blur )
|
||||
GaussianBlur(src, src, Size(5, 5), 1.5, 1.5);
|
||||
|
||||
int minRegs = use_big_image ? 7 : 2;
|
||||
int maxRegs = use_big_image ? 1000 : 20;
|
||||
if( binarize && (thresh == 0 || thresh == 255) )
|
||||
minRegs = maxRegs = 0;
|
||||
|
||||
mserExtractor->detectRegions( src, msers, boxes );
|
||||
int nmsers = (int)msers.size();
|
||||
ASSERT_EQ(nmsers, (int)boxes.size());
|
||||
|
||||
if( maxRegs < nmsers || minRegs > nmsers )
|
||||
{
|
||||
printf("%d. minArea=%d, maxArea=%d, nmsers=%d, minRegs=%d, maxRegs=%d, "
|
||||
"image=%s, invert=%d, binarize=%d, thresh=%d, blur=%d\n",
|
||||
i, kMinArea, kMaxArea, nmsers, minRegs, maxRegs, use_big_image ? "big" : "small",
|
||||
(int)invert, (int)binarize, thresh, (int)blur);
|
||||
#if defined RENDER_MSERS && RENDER_MSERS
|
||||
Mat image;
|
||||
imshow("source", src);
|
||||
renderMSERs(src, image, msers);
|
||||
imshow("result", image);
|
||||
waitKey();
|
||||
#endif
|
||||
}
|
||||
|
||||
ASSERT_LE(minRegs, nmsers);
|
||||
ASSERT_GE(maxRegs, nmsers);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Features2d_MSER, history_update_regression)
|
||||
{
|
||||
String dataPath = cvtest::TS::ptr()->get_data_path() + "mser/";
|
||||
vector<Mat> tstImages;
|
||||
tstImages.push_back(imread(dataPath + "mser_test.png", IMREAD_GRAYSCALE));
|
||||
tstImages.push_back(imread(dataPath + "mser_test2.png", IMREAD_GRAYSCALE));
|
||||
|
||||
for(size_t j = 0; j < tstImages.size(); j++)
|
||||
{
|
||||
size_t previous_size = 0;
|
||||
for(int minArea = 100; minArea > 10; minArea--)
|
||||
{
|
||||
Ptr<MSER> mser = MSER::create(1, minArea, (int)(tstImages[j].cols * tstImages[j].rows * 0.2));
|
||||
mser->setPass2Only(true);
|
||||
vector<vector<Point> > mserContours;
|
||||
vector<Rect> boxRects;
|
||||
mser->detectRegions(tstImages[j], mserContours, boxRects);
|
||||
ASSERT_LE(previous_size, mserContours.size());
|
||||
previous_size = mserContours.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace
|
333
3rdparty/opencv-4.5.4/modules/features2d/test/test_nearestneighbors.cpp
vendored
Normal file
333
3rdparty/opencv-4.5.4/modules/features2d/test/test_nearestneighbors.cpp
vendored
Normal file
@ -0,0 +1,333 @@
|
||||
/*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) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2014, Itseez Inc, 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
#ifdef HAVE_OPENCV_FLANN
|
||||
using namespace cv::flann;
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
class NearestNeighborTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
NearestNeighborTest() {}
|
||||
protected:
|
||||
static const int minValue = 0;
|
||||
static const int maxValue = 1;
|
||||
static const int dims = 30;
|
||||
static const int featuresCount = 2000;
|
||||
static const int K = 1; // * should also test 2nd nn etc.?
|
||||
|
||||
|
||||
virtual void run( int start_from );
|
||||
virtual void createModel( const Mat& data ) = 0;
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) = 0;
|
||||
virtual int checkGetPoints( const Mat& data );
|
||||
virtual int checkFindBoxed();
|
||||
virtual int checkFind( const Mat& data );
|
||||
virtual void releaseModel() = 0;
|
||||
};
|
||||
|
||||
int NearestNeighborTest::checkGetPoints( const Mat& )
|
||||
{
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
int NearestNeighborTest::checkFindBoxed()
|
||||
{
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
int NearestNeighborTest::checkFind( const Mat& data )
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
int pointsCount = 1000;
|
||||
float noise = 0.2f;
|
||||
|
||||
RNG rng;
|
||||
Mat points( pointsCount, dims, CV_32FC1 );
|
||||
Mat results( pointsCount, K, CV_32SC1 );
|
||||
|
||||
std::vector<int> fmap( pointsCount );
|
||||
for( int pi = 0; pi < pointsCount; pi++ )
|
||||
{
|
||||
int fi = rng.next() % featuresCount;
|
||||
fmap[pi] = fi;
|
||||
for( int d = 0; d < dims; d++ )
|
||||
points.at<float>(pi, d) = data.at<float>(fi, d) + rng.uniform(0.0f, 1.0f) * noise;
|
||||
}
|
||||
|
||||
code = findNeighbors( points, results );
|
||||
|
||||
if( code == cvtest::TS::OK )
|
||||
{
|
||||
int correctMatches = 0;
|
||||
for( int pi = 0; pi < pointsCount; pi++ )
|
||||
{
|
||||
if( fmap[pi] == results.at<int>(pi, 0) )
|
||||
correctMatches++;
|
||||
}
|
||||
|
||||
double correctPerc = correctMatches / (double)pointsCount;
|
||||
EXPECT_GE(correctPerc, .75) << "correctMatches=" << correctMatches << " pointsCount=" << pointsCount;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
void NearestNeighborTest::run( int /*start_from*/ ) {
|
||||
int code = cvtest::TS::OK, tempCode;
|
||||
Mat desc( featuresCount, dims, CV_32FC1 );
|
||||
ts->get_rng().fill( desc, RNG::UNIFORM, minValue, maxValue );
|
||||
|
||||
createModel( desc.clone() ); // .clone() is used to simulate dangling pointers problem: https://github.com/opencv/opencv/issues/17553
|
||||
|
||||
tempCode = checkGetPoints( desc );
|
||||
if( tempCode != cvtest::TS::OK )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of GetPoints \n" );
|
||||
code = tempCode;
|
||||
}
|
||||
|
||||
tempCode = checkFindBoxed();
|
||||
if( tempCode != cvtest::TS::OK )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of FindBoxed \n" );
|
||||
code = tempCode;
|
||||
}
|
||||
|
||||
tempCode = checkFind( desc );
|
||||
if( tempCode != cvtest::TS::OK )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of Find \n" );
|
||||
code = tempCode;
|
||||
}
|
||||
|
||||
releaseModel();
|
||||
|
||||
if (::testing::Test::HasFailure()) code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
#ifdef HAVE_OPENCV_FLANN
|
||||
|
||||
class CV_FlannTest : public NearestNeighborTest
|
||||
{
|
||||
public:
|
||||
CV_FlannTest() : NearestNeighborTest(), index(NULL) { }
|
||||
protected:
|
||||
void createIndex( const Mat& data, const IndexParams& params );
|
||||
int knnSearch( Mat& points, Mat& neighbors );
|
||||
int radiusSearch( Mat& points, Mat& neighbors );
|
||||
virtual void releaseModel();
|
||||
Index* index;
|
||||
};
|
||||
|
||||
void CV_FlannTest::createIndex( const Mat& data, const IndexParams& params )
|
||||
{
|
||||
// release previously allocated index
|
||||
releaseModel();
|
||||
|
||||
index = new Index( data, params );
|
||||
}
|
||||
|
||||
int CV_FlannTest::knnSearch( Mat& points, Mat& neighbors )
|
||||
{
|
||||
Mat dist( points.rows, neighbors.cols, CV_32FC1);
|
||||
int knn = 1, j;
|
||||
|
||||
// 1st way
|
||||
index->knnSearch( points, neighbors, dist, knn, SearchParams() );
|
||||
|
||||
// 2nd way
|
||||
Mat neighbors1( neighbors.size(), CV_32SC1 );
|
||||
for( int i = 0; i < points.rows; i++ )
|
||||
{
|
||||
float* fltPtr = points.ptr<float>(i);
|
||||
vector<float> query( fltPtr, fltPtr + points.cols );
|
||||
vector<int> indices( neighbors1.cols, 0 );
|
||||
vector<float> dists( dist.cols, 0 );
|
||||
index->knnSearch( query, indices, dists, knn, SearchParams() );
|
||||
vector<int>::const_iterator it = indices.begin();
|
||||
for( j = 0; it != indices.end(); ++it, j++ )
|
||||
neighbors1.at<int>(i,j) = *it;
|
||||
}
|
||||
|
||||
// compare results
|
||||
EXPECT_LE(cvtest::norm(neighbors, neighbors1, NORM_L1), 0);
|
||||
|
||||
return ::testing::Test::HasFailure() ? cvtest::TS::FAIL_BAD_ACCURACY : cvtest::TS::OK;
|
||||
}
|
||||
|
||||
int CV_FlannTest::radiusSearch( Mat& points, Mat& neighbors )
|
||||
{
|
||||
Mat dist( 1, neighbors.cols, CV_32FC1);
|
||||
Mat neighbors1( neighbors.size(), CV_32SC1 );
|
||||
float radius = 10.0f;
|
||||
int j;
|
||||
|
||||
// radiusSearch can only search one feature at a time for range search
|
||||
for( int i = 0; i < points.rows; i++ )
|
||||
{
|
||||
// 1st way
|
||||
Mat p( 1, points.cols, CV_32FC1, points.ptr<float>(i) ),
|
||||
n( 1, neighbors.cols, CV_32SC1, neighbors.ptr<int>(i) );
|
||||
index->radiusSearch( p, n, dist, radius, neighbors.cols, SearchParams() );
|
||||
|
||||
// 2nd way
|
||||
float* fltPtr = points.ptr<float>(i);
|
||||
vector<float> query( fltPtr, fltPtr + points.cols );
|
||||
vector<int> indices( neighbors1.cols, 0 );
|
||||
vector<float> dists( dist.cols, 0 );
|
||||
index->radiusSearch( query, indices, dists, radius, neighbors.cols, SearchParams() );
|
||||
vector<int>::const_iterator it = indices.begin();
|
||||
for( j = 0; it != indices.end(); ++it, j++ )
|
||||
neighbors1.at<int>(i,j) = *it;
|
||||
}
|
||||
|
||||
// compare results
|
||||
EXPECT_LE(cvtest::norm(neighbors, neighbors1, NORM_L1), 0);
|
||||
|
||||
return ::testing::Test::HasFailure() ? cvtest::TS::FAIL_BAD_ACCURACY : cvtest::TS::OK;
|
||||
}
|
||||
|
||||
void CV_FlannTest::releaseModel()
|
||||
{
|
||||
if (index)
|
||||
{
|
||||
delete index;
|
||||
index = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
class CV_FlannLinearIndexTest : public CV_FlannTest
|
||||
{
|
||||
public:
|
||||
CV_FlannLinearIndexTest() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data ) { createIndex( data, LinearIndexParams() ); }
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) { return knnSearch( points, neighbors ); }
|
||||
};
|
||||
|
||||
//---------------------------------------
|
||||
class CV_FlannKMeansIndexTest : public CV_FlannTest
|
||||
{
|
||||
public:
|
||||
CV_FlannKMeansIndexTest() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data ) { createIndex( data, KMeansIndexParams() ); }
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) { return radiusSearch( points, neighbors ); }
|
||||
};
|
||||
|
||||
//---------------------------------------
|
||||
class CV_FlannKDTreeIndexTest : public CV_FlannTest
|
||||
{
|
||||
public:
|
||||
CV_FlannKDTreeIndexTest() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data ) { createIndex( data, KDTreeIndexParams() ); }
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) { return radiusSearch( points, neighbors ); }
|
||||
};
|
||||
|
||||
//----------------------------------------
|
||||
class CV_FlannCompositeIndexTest : public CV_FlannTest
|
||||
{
|
||||
public:
|
||||
CV_FlannCompositeIndexTest() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data ) { createIndex( data, CompositeIndexParams() ); }
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) { return knnSearch( points, neighbors ); }
|
||||
};
|
||||
|
||||
//----------------------------------------
|
||||
class CV_FlannAutotunedIndexTest : public CV_FlannTest
|
||||
{
|
||||
public:
|
||||
CV_FlannAutotunedIndexTest() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data ) { createIndex( data, AutotunedIndexParams() ); }
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) { return knnSearch( points, neighbors ); }
|
||||
};
|
||||
//----------------------------------------
|
||||
class CV_FlannSavedIndexTest : public CV_FlannTest
|
||||
{
|
||||
public:
|
||||
CV_FlannSavedIndexTest() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data );
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) { return knnSearch( points, neighbors ); }
|
||||
};
|
||||
|
||||
void CV_FlannSavedIndexTest::createModel(const cv::Mat &data)
|
||||
{
|
||||
switch ( cvtest::randInt(ts->get_rng()) % 2 )
|
||||
{
|
||||
//case 0: createIndex( data, LinearIndexParams() ); break; // nothing to save for linear search
|
||||
case 0: createIndex( data, KMeansIndexParams() ); break;
|
||||
case 1: createIndex( data, KDTreeIndexParams() ); break;
|
||||
//case 2: createIndex( data, CompositeIndexParams() ); break; // nothing to save for linear search
|
||||
//case 2: createIndex( data, AutotunedIndexParams() ); break; // possible linear index !
|
||||
default: assert(0);
|
||||
}
|
||||
string filename = tempfile();
|
||||
index->save( filename );
|
||||
|
||||
createIndex( data, SavedIndexParams(filename.c_str()));
|
||||
remove( filename.c_str() );
|
||||
}
|
||||
|
||||
TEST(Features2d_FLANN_Linear, regression) { CV_FlannLinearIndexTest test; test.safe_run(); }
|
||||
TEST(Features2d_FLANN_KMeans, regression) { CV_FlannKMeansIndexTest test; test.safe_run(); }
|
||||
TEST(Features2d_FLANN_KDTree, regression) { CV_FlannKDTreeIndexTest test; test.safe_run(); }
|
||||
TEST(Features2d_FLANN_Composite, regression) { CV_FlannCompositeIndexTest test; test.safe_run(); }
|
||||
TEST(Features2d_FLANN_Auto, regression) { CV_FlannAutotunedIndexTest test; test.safe_run(); }
|
||||
TEST(Features2d_FLANN_Saved, regression) { CV_FlannSavedIndexTest test; test.safe_run(); }
|
||||
|
||||
#endif
|
||||
|
||||
}} // namespace
|
171
3rdparty/opencv-4.5.4/modules/features2d/test/test_orb.cpp
vendored
Normal file
171
3rdparty/opencv-4.5.4/modules/features2d/test/test_orb.cpp
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
/*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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(Features2D_ORB, _1996)
|
||||
{
|
||||
Ptr<FeatureDetector> fd = ORB::create(10000, 1.2f, 8, 31, 0, 2, ORB::HARRIS_SCORE, 31, 20);
|
||||
Ptr<DescriptorExtractor> de = fd;
|
||||
|
||||
Mat image = imread(string(cvtest::TS::ptr()->get_data_path()) + "shared/lena.png");
|
||||
ASSERT_FALSE(image.empty());
|
||||
|
||||
Mat roi(image.size(), CV_8UC1, Scalar(0));
|
||||
|
||||
Point poly[] = {Point(100, 20), Point(300, 50), Point(400, 200), Point(10, 500)};
|
||||
fillConvexPoly(roi, poly, int(sizeof(poly) / sizeof(poly[0])), Scalar(255));
|
||||
|
||||
std::vector<KeyPoint> keypoints;
|
||||
fd->detect(image, keypoints, roi);
|
||||
Mat descriptors;
|
||||
de->compute(image, keypoints, descriptors);
|
||||
|
||||
//image.setTo(Scalar(255,255,255), roi);
|
||||
|
||||
int roiViolations = 0;
|
||||
for(std::vector<KeyPoint>::const_iterator kp = keypoints.begin(); kp != keypoints.end(); ++kp)
|
||||
{
|
||||
int x = cvRound(kp->pt.x);
|
||||
int y = cvRound(kp->pt.y);
|
||||
|
||||
ASSERT_LE(0, x);
|
||||
ASSERT_LE(0, y);
|
||||
ASSERT_GT(image.cols, x);
|
||||
ASSERT_GT(image.rows, y);
|
||||
|
||||
// if (!roi.at<uchar>(y,x))
|
||||
// {
|
||||
// roiViolations++;
|
||||
// circle(image, kp->pt, 3, Scalar(0,0,255));
|
||||
// }
|
||||
}
|
||||
|
||||
// if(roiViolations)
|
||||
// {
|
||||
// imshow("img", image);
|
||||
// waitKey();
|
||||
// }
|
||||
|
||||
ASSERT_EQ(0, roiViolations);
|
||||
}
|
||||
|
||||
TEST(Features2D_ORB, crash_5031)
|
||||
{
|
||||
cv::Mat image = cv::Mat::zeros(cv::Size(1920, 1080), CV_8UC3);
|
||||
|
||||
int nfeatures = 8000;
|
||||
float orbScaleFactor = 1.2f;
|
||||
int nlevels = 18;
|
||||
int edgeThreshold = 4;
|
||||
int firstLevel = 0;
|
||||
int WTA_K = 2;
|
||||
ORB::ScoreType scoreType = cv::ORB::HARRIS_SCORE;
|
||||
int patchSize = 47;
|
||||
int fastThreshold = 20;
|
||||
|
||||
Ptr<ORB> orb = cv::ORB::create(nfeatures, orbScaleFactor, nlevels, edgeThreshold, firstLevel, WTA_K, scoreType, patchSize, fastThreshold);
|
||||
|
||||
std::vector<cv::KeyPoint> keypoints;
|
||||
cv::Mat descriptors;
|
||||
|
||||
cv::KeyPoint kp;
|
||||
kp.pt.x = 443;
|
||||
kp.pt.y = 5;
|
||||
kp.size = 47;
|
||||
kp.angle = 53.4580612f;
|
||||
kp.response = 0.0000470733867f;
|
||||
kp.octave = 0;
|
||||
kp.class_id = -1;
|
||||
|
||||
keypoints.push_back(kp);
|
||||
|
||||
ASSERT_NO_THROW(orb->compute(image, keypoints, descriptors));
|
||||
}
|
||||
|
||||
|
||||
TEST(Features2D_ORB, regression_16197)
|
||||
{
|
||||
Mat img(Size(72, 72), CV_8UC1, Scalar::all(0));
|
||||
Ptr<ORB> orbPtr = ORB::create();
|
||||
orbPtr->setNLevels(5);
|
||||
orbPtr->setFirstLevel(3);
|
||||
orbPtr->setScaleFactor(1.8);
|
||||
orbPtr->setPatchSize(8);
|
||||
orbPtr->setEdgeThreshold(8);
|
||||
|
||||
std::vector<KeyPoint> kps;
|
||||
Mat fv;
|
||||
|
||||
// exception in debug mode, crash in release
|
||||
ASSERT_NO_THROW(orbPtr->detectAndCompute(img, noArray(), kps, fv));
|
||||
}
|
||||
|
||||
// https://github.com/opencv/opencv-python/issues/537
|
||||
BIGDATA_TEST(Features2D_ORB, regression_opencv_python_537) // memory usage: ~3 Gb
|
||||
{
|
||||
applyTestTag(
|
||||
CV_TEST_TAG_LONG,
|
||||
CV_TEST_TAG_DEBUG_VERYLONG,
|
||||
CV_TEST_TAG_MEMORY_6GB
|
||||
);
|
||||
|
||||
const int width = 25000;
|
||||
const int height = 25000;
|
||||
Mat img(Size(width, height), CV_8UC1, Scalar::all(0));
|
||||
|
||||
const int border = 23, num_lines = 23;
|
||||
for (int i = 0; i < num_lines; i++)
|
||||
{
|
||||
cv::Point2i point1(border + i * 100, border + i * 100);
|
||||
cv::Point2i point2(width - border - i * 100, height - border * i * 100);
|
||||
cv::line(img, point1, point2, 255, 1, LINE_AA);
|
||||
}
|
||||
|
||||
Ptr<ORB> orbPtr = ORB::create(31);
|
||||
std::vector<KeyPoint> kps;
|
||||
Mat fv;
|
||||
ASSERT_NO_THROW(orbPtr->detectAndCompute(img, noArray(), kps, fv));
|
||||
}
|
||||
|
||||
}} // namespace
|
10
3rdparty/opencv-4.5.4/modules/features2d/test/test_precomp.hpp
vendored
Normal file
10
3rdparty/opencv-4.5.4/modules/features2d/test/test_precomp.hpp
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
// 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.
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts.hpp"
|
||||
#include "opencv2/features2d.hpp"
|
||||
|
||||
#endif
|
34
3rdparty/opencv-4.5.4/modules/features2d/test/test_sift.cpp
vendored
Normal file
34
3rdparty/opencv-4.5.4/modules/features2d/test/test_sift.cpp
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
// 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_SIFT, descriptor_type)
|
||||
{
|
||||
Mat image = imread(cvtest::findDataFile("features2d/tsukuba.png"));
|
||||
ASSERT_FALSE(image.empty());
|
||||
|
||||
Mat gray;
|
||||
cvtColor(image, gray, COLOR_BGR2GRAY);
|
||||
|
||||
vector<KeyPoint> keypoints;
|
||||
Mat descriptorsFloat, descriptorsUchar;
|
||||
Ptr<SIFT> siftFloat = cv::SIFT::create(0, 3, 0.04, 10, 1.6, CV_32F);
|
||||
siftFloat->detectAndCompute(gray, Mat(), keypoints, descriptorsFloat, false);
|
||||
ASSERT_EQ(descriptorsFloat.type(), CV_32F) << "type mismatch";
|
||||
|
||||
Ptr<SIFT> siftUchar = cv::SIFT::create(0, 3, 0.04, 10, 1.6, CV_8U);
|
||||
siftUchar->detectAndCompute(gray, Mat(), keypoints, descriptorsUchar, false);
|
||||
ASSERT_EQ(descriptorsUchar.type(), CV_8U) << "type mismatch";
|
||||
|
||||
Mat descriptorsFloat2;
|
||||
descriptorsUchar.assignTo(descriptorsFloat2, CV_32F);
|
||||
Mat diff = descriptorsFloat != descriptorsFloat2;
|
||||
ASSERT_EQ(countNonZero(diff), 0) << "descriptors are not identical";
|
||||
}
|
||||
|
||||
|
||||
}} // namespace
|
38
3rdparty/opencv-4.5.4/modules/features2d/test/test_utils.cpp
vendored
Normal file
38
3rdparty/opencv-4.5.4/modules/features2d/test/test_utils.cpp
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
// 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_KeypointUtils, retainBest_issue_12594)
|
||||
{
|
||||
const size_t N = 9;
|
||||
|
||||
// Construct 4-way tie for 3rd highest - correct answer for "3 best" is 6
|
||||
const float no_problem[] = { 5.0f, 4.0f, 1.0f, 2.0f, 0.0f, 3.0f, 3.0f, 3.0f, 3.0f };
|
||||
|
||||
// Same set, different order that exposes partial sort property of std::nth_element
|
||||
// Note: the problem case may depend on your particular implementation of STL
|
||||
const float problem[] = { 3.0f, 3.0f, 3.0f, 3.0f, 4.0f, 5.0f, 0.0f, 1.0f, 2.0f };
|
||||
|
||||
const size_t NBEST = 3u;
|
||||
const size_t ANSWER = 6u;
|
||||
|
||||
std::vector<cv::KeyPoint> sorted_cv(N);
|
||||
std::vector<cv::KeyPoint> unsorted_cv(N);
|
||||
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
sorted_cv[i].response = no_problem[i];
|
||||
unsorted_cv[i].response = problem[i];
|
||||
}
|
||||
|
||||
cv::KeyPointsFilter::retainBest(sorted_cv, NBEST);
|
||||
cv::KeyPointsFilter::retainBest(unsorted_cv, NBEST);
|
||||
|
||||
EXPECT_EQ(ANSWER, sorted_cv.size());
|
||||
EXPECT_EQ(ANSWER, unsorted_cv.size());
|
||||
}
|
||||
|
||||
}} // namespace
|
Reference in New Issue
Block a user