diff --git a/modules/features2d/test/test_nearestneighbors.cpp b/modules/features2d/test/test_nearestneighbors.cpp index f63ebb8d92..0ea86a8277 100644 --- a/modules/features2d/test/test_nearestneighbors.cpp +++ b/modules/features2d/test/test_nearestneighbors.cpp @@ -123,7 +123,7 @@ void NearestNeighborTest::run( int /*start_from*/ ) { Mat desc( featuresCount, dims, CV_32FC1 ); ts->get_rng().fill( desc, RNG::UNIFORM, minValue, maxValue ); - createModel( desc ); + 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 ) diff --git a/modules/flann/include/opencv2/flann/miniflann.hpp b/modules/flann/include/opencv2/flann/miniflann.hpp index 093646254c..b8df92d758 100644 --- a/modules/flann/include/opencv2/flann/miniflann.hpp +++ b/modules/flann/include/opencv2/flann/miniflann.hpp @@ -169,10 +169,13 @@ public: CV_WRAP cvflann::flann_algorithm_t getAlgorithm() const; protected: + bool load_(const String& filename); + cvflann::flann_distance_t distType; cvflann::flann_algorithm_t algo; int featureType; void* index; + Mat features_clone; // index may store features pointer internally for searching, so avoid dangling pointers: https://github.com/opencv/opencv/issues/17553 }; } } // namespace cv::flann diff --git a/modules/flann/src/miniflann.cpp b/modules/flann/src/miniflann.cpp index b56578c17f..c871875ae4 100644 --- a/modules/flann/src/miniflann.cpp +++ b/modules/flann/src/miniflann.cpp @@ -390,14 +390,18 @@ void Index::build(InputArray _data, const IndexParams& params, flann_distance_t CV_INSTRUMENT_REGION(); release(); + + // Index may reuse 'data' during search, need to keep it alive + features_clone = _data.getMat().clone(); + Mat data = features_clone; + algo = getParam(params, "algorithm", FLANN_INDEX_LINEAR); if( algo == FLANN_INDEX_SAVED ) { - load(_data, getParam(params, "filename", String())); + load_(getParam(params, "filename", String())); return; } - Mat data = _data.getMat(); index = 0; featureType = data.type(); distType = _distType; @@ -462,6 +466,8 @@ void Index::release() { CV_INSTRUMENT_REGION(); + features_clone.release(); + if( !index ) return; @@ -785,9 +791,20 @@ bool loadIndex(Index* index0, void*& index, const Mat& data, FILE* fin, const Di bool Index::load(InputArray _data, const String& filename) { - Mat data = _data.getMat(); - bool ok = true; release(); + + // Index may reuse 'data' during search, need to keep it alive + features_clone = _data.getMat().clone(); + Mat data = features_clone; + + return load_(filename); +} + +bool Index::load_(const String& filename) +{ + Mat data = features_clone; + bool ok = true; + FILE* fin = fopen(filename.c_str(), "rb"); if (fin == NULL) return false;