mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 00:03:03 +04:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
@@ -86,12 +86,24 @@ namespace cv { namespace debug_build_guard { } using namespace debug_build_guard
|
||||
#define __CV_VA_NUM_ARGS_HELPER(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
|
||||
#define __CV_VA_NUM_ARGS(...) __CV_EXPAND(__CV_VA_NUM_ARGS_HELPER(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
|
||||
|
||||
#if defined __GNUC__
|
||||
#ifdef CV_Func
|
||||
// keep current value (through OpenCV port file)
|
||||
#elif defined __GNUC__ || (defined (__cpluscplus) && (__cpluscplus >= 201103))
|
||||
#define CV_Func __func__
|
||||
#elif defined __clang__ && (__clang_minor__ * 100 + __clang_major >= 305)
|
||||
#define CV_Func __func__
|
||||
#elif defined(__STDC_VERSION__) && (__STDC_VERSION >= 199901)
|
||||
#define CV_Func __func__
|
||||
#elif defined _MSC_VER
|
||||
#define CV_Func __FUNCTION__
|
||||
#elif defined(__INTEL_COMPILER) && (_INTEL_COMPILER >= 600)
|
||||
#define CV_Func __FUNCTION__
|
||||
#elif defined __IBMCPP__ && __IBMCPP__ >=500
|
||||
#define CV_Func __FUNCTION__
|
||||
#elif defined __BORLAND__ && (__BORLANDC__ >= 0x550)
|
||||
#define CV_Func __FUNC__
|
||||
#else
|
||||
#define CV_Func ""
|
||||
#define CV_Func "<unknown>"
|
||||
#endif
|
||||
|
||||
//! @cond IGNORED
|
||||
|
||||
@@ -261,6 +261,10 @@ public:
|
||||
@param contrastThreshold The contrast threshold used to filter out weak features in semi-uniform
|
||||
(low-contrast) regions. The larger the threshold, the less features are produced by the detector.
|
||||
|
||||
@note The contrast threshold will be divided by nOctaveLayers when the filtering is applied. When
|
||||
nOctaveLayers is set to default and if you want to use the value used in D. Lowe paper, 0.03, set
|
||||
this argument to 0.09.
|
||||
|
||||
@param edgeThreshold The threshold used to filter out edge-like features. Note that the its meaning
|
||||
is different from the contrastThreshold, i.e. the larger the edgeThreshold, the less features are
|
||||
filtered out (more features are retained).
|
||||
@@ -271,6 +275,8 @@ public:
|
||||
CV_WRAP static Ptr<SIFT> create(int nfeatures = 0, int nOctaveLayers = 3,
|
||||
double contrastThreshold = 0.04, double edgeThreshold = 10,
|
||||
double sigma = 1.6);
|
||||
|
||||
CV_WRAP virtual String getDefaultName() const CV_OVERRIDE;
|
||||
};
|
||||
|
||||
typedef SIFT SiftFeatureDetector;
|
||||
|
||||
@@ -21,7 +21,8 @@ namespace opencv_test
|
||||
ORB_DEFAULT, ORB_1500_13_1, \
|
||||
AKAZE_DEFAULT, AKAZE_DESCRIPTOR_KAZE, \
|
||||
BRISK_DEFAULT, \
|
||||
KAZE_DEFAULT
|
||||
KAZE_DEFAULT, \
|
||||
SIFT_DEFAULT
|
||||
|
||||
#define CV_ENUM_EXPAND(name, ...) CV_ENUM(name, __VA_ARGS__)
|
||||
|
||||
@@ -77,6 +78,8 @@ static inline Ptr<Feature2D> getFeature2D(Feature2DType type)
|
||||
return KAZE::create();
|
||||
case MSER_DEFAULT:
|
||||
return MSER::create();
|
||||
case SIFT_DEFAULT:
|
||||
return SIFT::create();
|
||||
default:
|
||||
return Ptr<Feature2D>();
|
||||
}
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
// 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 "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
typedef perf::TestBaseWithParam<std::string> SIFT_detect;
|
||||
typedef perf::TestBaseWithParam<std::string> SIFT_extract;
|
||||
typedef perf::TestBaseWithParam<std::string> SIFT_full;
|
||||
|
||||
#define SIFT_IMAGES \
|
||||
"cv/detectors_descriptors_evaluation/images_datasets/leuven/img1.png",\
|
||||
"stitching/a3.png"
|
||||
|
||||
PERF_TEST_P_(SIFT_detect, SIFT)
|
||||
{
|
||||
string filename = getDataPath(GetParam());
|
||||
Mat frame = imread(filename, IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(frame.empty()) << "Unable to load source image " << filename;
|
||||
|
||||
Mat mask;
|
||||
declare.in(frame).time(90);
|
||||
Ptr<SIFT> detector = SIFT::create();
|
||||
vector<KeyPoint> points;
|
||||
|
||||
PERF_SAMPLE_BEGIN();
|
||||
detector->detect(frame, points, mask);
|
||||
PERF_SAMPLE_END();
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST_P_(SIFT_extract, SIFT)
|
||||
{
|
||||
string filename = getDataPath(GetParam());
|
||||
Mat frame = imread(filename, IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(frame.empty()) << "Unable to load source image " << filename;
|
||||
|
||||
Mat mask;
|
||||
declare.in(frame).time(90);
|
||||
|
||||
Ptr<SIFT> detector = SIFT::create();
|
||||
vector<KeyPoint> points;
|
||||
Mat descriptors;
|
||||
detector->detect(frame, points, mask);
|
||||
|
||||
PERF_SAMPLE_BEGIN();
|
||||
detector->compute(frame, points, descriptors);
|
||||
PERF_SAMPLE_END();
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST_P_(SIFT_full, SIFT)
|
||||
{
|
||||
string filename = getDataPath(GetParam());
|
||||
Mat frame = imread(filename, IMREAD_GRAYSCALE);
|
||||
ASSERT_FALSE(frame.empty()) << "Unable to load source image " << filename;
|
||||
|
||||
Mat mask;
|
||||
declare.in(frame).time(90);
|
||||
Ptr<SIFT> detector = SIFT::create();
|
||||
vector<KeyPoint> points;
|
||||
Mat descriptors;
|
||||
|
||||
PERF_SAMPLE_BEGIN();
|
||||
detector->detectAndCompute(frame, mask, points, descriptors, false);
|
||||
PERF_SAMPLE_END();
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, SIFT_detect,
|
||||
testing::Values(SIFT_IMAGES)
|
||||
);
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, SIFT_extract,
|
||||
testing::Values(SIFT_IMAGES)
|
||||
);
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, SIFT_full,
|
||||
testing::Values(SIFT_IMAGES)
|
||||
);
|
||||
|
||||
}} // namespace
|
||||
@@ -126,6 +126,11 @@ Ptr<SIFT> SIFT::create( int _nfeatures, int _nOctaveLayers,
|
||||
return makePtr<SIFT_Impl>(_nfeatures, _nOctaveLayers, _contrastThreshold, _edgeThreshold, _sigma);
|
||||
}
|
||||
|
||||
String SIFT::getDefaultName() const
|
||||
{
|
||||
return (Feature2D::getDefaultName() + ".SIFT");
|
||||
}
|
||||
|
||||
static inline void
|
||||
unpackOctave(const KeyPoint& kpt, int& octave, int& layer, float& scale)
|
||||
{
|
||||
|
||||
@@ -36,9 +36,8 @@ INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, DescriptorRotationInvariance,
|
||||
* Descriptor's scale invariance check
|
||||
*/
|
||||
|
||||
// TODO: Expected: (descInliersRatio) >= (minInliersRatio), actual: 0.330378 vs 0.78
|
||||
INSTANTIATE_TEST_CASE_P(DISABLED_SIFT, DescriptorScaleInvariance,
|
||||
Value(IMAGE_BIKES, SIFT::create(), SIFT::create(), 0.78f));
|
||||
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));
|
||||
|
||||
@@ -12,6 +12,26 @@ 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)
|
||||
{
|
||||
@@ -129,6 +149,10 @@ TEST_P(DescriptorScaleInvariance, scale)
|
||||
|
||||
vector<KeyPoint> keypoints1;
|
||||
scaleKeyPoints(keypoints0, keypoints1, 1.0f/scale);
|
||||
if (featureDetector->getDefaultName() == "Feature2D.SIFT")
|
||||
{
|
||||
SetSuitableSIFTOctave(keypoints1);
|
||||
}
|
||||
Mat descriptors1;
|
||||
descriptorExtractor->compute(image1, keypoints1, descriptors1);
|
||||
|
||||
|
||||
@@ -36,9 +36,8 @@ INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, DetectorRotationInvariance,
|
||||
* Detector's scale invariance check
|
||||
*/
|
||||
|
||||
// TODO: Expected: (keyPointMatchesRatio) >= (minKeyPointMatchesRatio), actual: 0.596752 vs 0.69
|
||||
INSTANTIATE_TEST_CASE_P(DISABLED_SIFT, DetectorScaleInvariance,
|
||||
Value(IMAGE_BIKES, SIFT::create(), 0.69f, 0.98f));
|
||||
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));
|
||||
|
||||
@@ -708,7 +708,7 @@ struct KL_Divergence
|
||||
Iterator1 last = a + size;
|
||||
|
||||
while (a < last) {
|
||||
if (* b != 0) {
|
||||
if ( *a != 0 && *b != 0 ) {
|
||||
ResultType ratio = (ResultType)(*a / *b);
|
||||
if (ratio>0) {
|
||||
result += *a * log(ratio);
|
||||
@@ -731,7 +731,7 @@ struct KL_Divergence
|
||||
inline ResultType accum_dist(const U& a, const V& b, int) const
|
||||
{
|
||||
ResultType result = ResultType();
|
||||
if( *b != 0 ) {
|
||||
if( a != 0 && b != 0 ) {
|
||||
ResultType ratio = (ResultType)(a / b);
|
||||
if (ratio>0) {
|
||||
result = a * log(ratio);
|
||||
|
||||
@@ -461,7 +461,7 @@ private:
|
||||
DistanceType span = bbox[i].high-bbox[i].low;
|
||||
if (span>(DistanceType)((1-EPS)*max_span)) {
|
||||
ElementType min_elem, max_elem;
|
||||
computeMinMax(ind, count, cutfeat, min_elem, max_elem);
|
||||
computeMinMax(ind, count, (int)i, min_elem, max_elem);
|
||||
DistanceType spread = (DistanceType)(max_elem-min_elem);
|
||||
if (spread>max_spread) {
|
||||
cutfeat = (int)i;
|
||||
@@ -548,11 +548,19 @@ private:
|
||||
/* If this is a leaf node, then do check and return. */
|
||||
if ((node->child1 == NULL)&&(node->child2 == NULL)) {
|
||||
DistanceType worst_dist = result_set.worstDist();
|
||||
for (int i=node->left; i<node->right; ++i) {
|
||||
int index = reorder_ ? i : vind_[i];
|
||||
DistanceType dist = distance_(vec, data_[index], dim_, worst_dist);
|
||||
if (dist<worst_dist) {
|
||||
result_set.addPoint(dist,vind_[i]);
|
||||
if (reorder_) {
|
||||
for (int i=node->left; i<node->right; ++i) {
|
||||
DistanceType dist = distance_(vec, data_[i], dim_, worst_dist);
|
||||
if (dist<worst_dist) {
|
||||
result_set.addPoint(dist,vind_[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i=node->left; i<node->right; ++i) {
|
||||
DistanceType dist = distance_(vec, data_[vind_[i]], dim_, worst_dist);
|
||||
if (dist<worst_dist) {
|
||||
result_set.addPoint(dist,vind_[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -650,7 +650,8 @@ private:
|
||||
*
|
||||
* Params:
|
||||
* node = the node to use
|
||||
* indices = the indices of the points belonging to the node
|
||||
* indices = array of indices of the points belonging to the node
|
||||
* indices_length = number of indices in the array
|
||||
*/
|
||||
void computeNodeStatistics(KMeansNodePtr node, int* indices, int indices_length)
|
||||
{
|
||||
@@ -662,7 +663,7 @@ private:
|
||||
|
||||
memset(mean,0,veclen_*sizeof(DistanceType));
|
||||
|
||||
for (size_t i=0; i<size_; ++i) {
|
||||
for (size_t i=0; i<(size_t)indices_length; ++i) {
|
||||
ElementType* vec = dataset_[indices[i]];
|
||||
for (size_t j=0; j<veclen_; ++j) {
|
||||
mean[j] += vec[j];
|
||||
|
||||
@@ -60,20 +60,20 @@ struct LshIndexParams : public IndexParams
|
||||
{
|
||||
LshIndexParams(unsigned int table_number = 12, unsigned int key_size = 20, unsigned int multi_probe_level = 2)
|
||||
{
|
||||
(* this)["algorithm"] = FLANN_INDEX_LSH;
|
||||
(*this)["algorithm"] = FLANN_INDEX_LSH;
|
||||
// The number of hash tables to use
|
||||
(*this)["table_number"] = table_number;
|
||||
(*this)["table_number"] = static_cast<int>(table_number);
|
||||
// The length of the key in the hash tables
|
||||
(*this)["key_size"] = key_size;
|
||||
(*this)["key_size"] = static_cast<int>(key_size);
|
||||
// Number of levels to use in multi-probe (0 for standard LSH)
|
||||
(*this)["multi_probe_level"] = multi_probe_level;
|
||||
(*this)["multi_probe_level"] = static_cast<int>(multi_probe_level);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Randomized kd-tree index
|
||||
* Locality-sensitive hashing index
|
||||
*
|
||||
* Contains the k-d trees and other information for indexing a set of points
|
||||
* Contains the tables and other information for indexing a set of points
|
||||
* for nearest-neighbor matching.
|
||||
*/
|
||||
template<typename Distance>
|
||||
@@ -94,9 +94,9 @@ public:
|
||||
{
|
||||
// cv::flann::IndexParams sets integer params as 'int', so it is used with get_param
|
||||
// in place of 'unsigned int'
|
||||
table_number_ = (unsigned int)get_param<int>(index_params_,"table_number",12);
|
||||
key_size_ = (unsigned int)get_param<int>(index_params_,"key_size",20);
|
||||
multi_probe_level_ = (unsigned int)get_param<int>(index_params_,"multi_probe_level",2);
|
||||
table_number_ = get_param(index_params_,"table_number",12);
|
||||
key_size_ = get_param(index_params_,"key_size",20);
|
||||
multi_probe_level_ = get_param(index_params_,"multi_probe_level",2);
|
||||
|
||||
feature_size_ = (unsigned)dataset_.cols;
|
||||
fill_xor_mask(0, key_size_, multi_probe_level_, xor_masks_);
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
void buildIndex() CV_OVERRIDE
|
||||
{
|
||||
tables_.resize(table_number_);
|
||||
for (unsigned int i = 0; i < table_number_; ++i) {
|
||||
for (int i = 0; i < table_number_; ++i) {
|
||||
lsh::LshTable<ElementType>& table = tables_[i];
|
||||
table = lsh::LshTable<ElementType>(feature_size_, key_size_);
|
||||
|
||||
@@ -378,11 +378,11 @@ private:
|
||||
IndexParams index_params_;
|
||||
|
||||
/** table number */
|
||||
unsigned int table_number_;
|
||||
int table_number_;
|
||||
/** key size */
|
||||
unsigned int key_size_;
|
||||
int key_size_;
|
||||
/** How far should we look for neighbors in multi-probe LSH */
|
||||
unsigned int multi_probe_level_;
|
||||
int multi_probe_level_;
|
||||
|
||||
/** The XOR masks to apply to a key to get the neighboring buckets */
|
||||
std::vector<lsh::BucketKey> xor_masks_;
|
||||
|
||||
@@ -245,7 +245,7 @@ public:
|
||||
{
|
||||
std::cerr << "LSH is not implemented for that type" << std::endl;
|
||||
assert(0);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Get statistics about the table
|
||||
|
||||
@@ -196,12 +196,10 @@ public:
|
||||
#endif
|
||||
{
|
||||
// Check for duplicate indices
|
||||
int j = i - 1;
|
||||
while ((j >= 0) && (dists[j] == dist)) {
|
||||
for (int j = i; dists[j] == dist && j--;) {
|
||||
if (indices[j] == index) {
|
||||
return;
|
||||
}
|
||||
--j;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -90,4 +90,10 @@ void CV_LshTableBadArgTest::run( int /* start_from */ )
|
||||
|
||||
TEST(Flann_LshTable, badarg) { CV_LshTableBadArgTest test; test.safe_run(); }
|
||||
|
||||
TEST(Flann_LshTable, bad_any_cast) {
|
||||
Mat features = Mat::ones(1, 64, CV_8U);
|
||||
EXPECT_NO_THROW(flann::GenericIndex<cvflann::Hamming2<unsigned char> >(
|
||||
features, cvflann::LshIndexParams()));
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -112,6 +112,21 @@ void UIImageToMat(const UIImage* image,
|
||||
m.step[0], colorSpace,
|
||||
bitmapInfo);
|
||||
}
|
||||
else if (CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelIndexed)
|
||||
{
|
||||
// CGBitmapContextCreate() does not support indexed color spaces.
|
||||
colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
m.create(rows, cols, CV_8UC4); // 8 bits per component, 4 channels
|
||||
if (!alphaExist)
|
||||
bitmapInfo = kCGImageAlphaNoneSkipLast |
|
||||
kCGBitmapByteOrderDefault;
|
||||
else
|
||||
m = cv::Scalar(0);
|
||||
contextRef = CGBitmapContextCreate(m.data, m.cols, m.rows, 8,
|
||||
m.step[0], colorSpace,
|
||||
bitmapInfo);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
}
|
||||
else
|
||||
{
|
||||
m.create(rows, cols, CV_8UC4); // 8 bits per component, 4 channels
|
||||
|
||||
Reference in New Issue
Block a user