From a66fd527b05d3e6cfc6ea68a4156dab8b6ea18c2 Mon Sep 17 00:00:00 2001 From: jasjuang Date: Mon, 15 Oct 2018 10:40:24 -0700 Subject: [PATCH 01/10] add support for latest Turing gpu and cuda 10 --- cmake/OpenCVDetectCUDA.cmake | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cmake/OpenCVDetectCUDA.cmake b/cmake/OpenCVDetectCUDA.cmake index 76e57c8fc9..ee4e7cea64 100644 --- a/cmake/OpenCVDetectCUDA.cmake +++ b/cmake/OpenCVDetectCUDA.cmake @@ -81,6 +81,8 @@ if(CUDA_FOUND) set(__cuda_arch_bin "6.0 6.1") elseif(CUDA_GENERATION STREQUAL "Volta") set(__cuda_arch_bin "7.0") + elseif(CUDA_GENERATION STREQUAL "Turing") + set(__cuda_arch_bin "7.5") elseif(CUDA_GENERATION STREQUAL "Auto") execute_process( COMMAND "${CUDA_NVCC_EXECUTABLE}" ${CUDA_NVCC_FLAGS} "${OpenCV_SOURCE_DIR}/cmake/checks/OpenCVDetectCudaArch.cu" "--run" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/" @@ -105,7 +107,7 @@ if(CUDA_FOUND) ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT _nvcc_res EQUAL 0) message(STATUS "Automatic detection of CUDA generation failed. Going to build for all known architectures.") - set(__cuda_arch_bin "5.3 6.2 7.0") + set(__cuda_arch_bin "5.3 6.2 7.0 7.5") else() set(__cuda_arch_bin "${_nvcc_out}") string(REPLACE "2.1" "2.1(2.0)" __cuda_arch_bin "${__cuda_arch_bin}") @@ -114,8 +116,10 @@ if(CUDA_FOUND) else() if(${CUDA_VERSION} VERSION_LESS "9.0") set(__cuda_arch_bin "2.0 3.0 3.5 3.7 5.0 5.2 6.0 6.1") - else() + elseif(${CUDA_VERSION} VERSION_LESS "10.0") set(__cuda_arch_bin "3.0 3.5 3.7 5.0 5.2 6.0 6.1 7.0") + else() + set(__cuda_arch_bin "3.0 3.5 3.7 5.0 5.2 6.0 6.1 7.0 7.5") endif() endif() endif() From 1c468add2035467fe36e2d0c1bf1d008bf15a1b3 Mon Sep 17 00:00:00 2001 From: Paul Shin Date: Mon, 15 Oct 2018 20:03:39 -0700 Subject: [PATCH 02/10] Increased the acceptable error margin for perf testing - This is to accommodate the variabiilty in floating-point operations in new platforms/compilers - Specifically due to the error margin found in NVIDIA Jetson TX2 --- modules/stitching/perf/perf_matchers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/stitching/perf/perf_matchers.cpp b/modules/stitching/perf/perf_matchers.cpp index 505fe59449..28e19c85f3 100644 --- a/modules/stitching/perf/perf_matchers.cpp +++ b/modules/stitching/perf/perf_matchers.cpp @@ -103,7 +103,7 @@ PERF_TEST_P( match, bestOf2Nearest, TEST_DETECTORS) Mat R (pairwise_matches.H, Range::all(), Range(0, 2)); // separate transform matrix, use lower error on rotations SANITY_CHECK(dist, 1., ERROR_ABSOLUTE); - SANITY_CHECK(R, .015, ERROR_ABSOLUTE); + SANITY_CHECK(R, .06, ERROR_ABSOLUTE); } PERF_TEST_P( matchVector, bestOf2NearestVectorFeatures, testing::Combine( From c8e6ce304f8f113d334227c6fcec3d5f696d1c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Tue, 16 Oct 2018 21:09:26 +0200 Subject: [PATCH 03/10] Catch exceptions by const-reference Exceptions caught by value incur needless cost in C++, most of them can be caught by const-reference, especially as nearly none are actually used. This could allow compiler generate a slightly more efficient code. --- modules/core/src/copy.cpp | 2 +- modules/core/test/test_ds.cpp | 10 +++++----- modules/imgproc/src/canny.cpp | 4 ++-- modules/imgproc/src/deriv.cpp | 4 ++-- modules/imgproc/src/morph.cpp | 2 +- modules/imgproc/src/resize.cpp | 6 +++--- modules/imgproc/src/smooth.cpp | 10 +++++----- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index 98ab15d4ca..7fb850ee38 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -729,7 +729,7 @@ static bool ipp_flip(Mat &src, Mat &dst, int flip_mode) CV_INSTRUMENT_FUN_IPP(::ipp::iwiMirror, iwSrc, iwDst, ippMode); } - catch(::ipp::IwException) + catch(const ::ipp::IwException &) { return false; } diff --git a/modules/core/test/test_ds.cpp b/modules/core/test/test_ds.cpp index 3a1a00b8b6..64d54c5966 100644 --- a/modules/core/test/test_ds.cpp +++ b/modules/core/test/test_ds.cpp @@ -1032,7 +1032,7 @@ void Core_SeqBaseTest::run( int ) cvClearMemStorage( storage ); } } - catch(int) + catch(const int &) { } } @@ -1200,7 +1200,7 @@ void Core_SeqSortInvTest::run( int ) storage.release(); } } - catch (int) + catch (const int &) { } } @@ -1416,7 +1416,7 @@ void Core_SetTest::run( int ) storage.release(); } } - catch(int) + catch(const int &) { } } @@ -1859,7 +1859,7 @@ void Core_GraphTest::run( int ) storage.release(); } } - catch(int) + catch(const int &) { } } @@ -2121,7 +2121,7 @@ void Core_GraphScanTest::run( int ) storage.release(); } } - catch(int) + catch(const int &) { } } diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 22c24eaf63..89eac241c1 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -93,7 +93,7 @@ static bool ipp_Canny(const Mat& src , const Mat& dx_, const Mat& dy_, Mat& dst, CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterCannyDeriv, iwSrcDx, iwSrcDy, iwDst, low, high, ::ipp::IwiFilterCannyDerivParams(norm)); } - catch (::ipp::IwException ex) + catch (const ::ipp::IwException &) { return false; } @@ -119,7 +119,7 @@ static bool ipp_Canny(const Mat& src , const Mat& dx_, const Mat& dy_, Mat& dst, CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterCanny, iwSrc, iwDst, low, high, ::ipp::IwiFilterCannyParams(ippFilterSobel, kernel, norm), ippBorderRepl); } - catch (::ipp::IwException) + catch (const ::ipp::IwException &) { return false; } diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index a2e339c843..b83feceda9 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -337,7 +337,7 @@ static bool ipp_Deriv(InputArray _src, OutputArray _dst, int dx, int dy, int ksi if(useScale) CV_INSTRUMENT_FUN_IPP(::ipp::iwiScale, iwDstProc, iwDst, scale, delta, ::ipp::IwiScaleParams(ippAlgHintFast)); } - catch (::ipp::IwException) + catch (const ::ipp::IwException &) { return false; } @@ -765,7 +765,7 @@ static bool ipp_Laplacian(InputArray _src, OutputArray _dst, int ksize, double s CV_INSTRUMENT_FUN_IPP(::ipp::iwiScale, iwDstProc, iwDst, scale, delta); } - catch (::ipp::IwException ex) + catch (const ::ipp::IwException &) { return false; } diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 66fae07fae..08a9969394 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1299,7 +1299,7 @@ static bool ippMorph(int op, int src_type, int dst_type, CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterMorphology, iwSrc, iwDst, morphType, iwMask, ::ipp::IwDefault(), iwBorderType); } } - catch(::ipp::IwException ex) + catch(const ::ipp::IwException &) { return false; } diff --git a/modules/imgproc/src/resize.cpp b/modules/imgproc/src/resize.cpp index 688f4c7ff0..7eeefc7098 100644 --- a/modules/imgproc/src/resize.cpp +++ b/modules/imgproc/src/resize.cpp @@ -3241,7 +3241,7 @@ public: ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, m_dst.m_size.width, range.end - range.start); CV_INSTRUMENT_FUN_IPP(iwiResize, m_src, m_dst, ippBorderRepl, tile); } - catch(::ipp::IwException) + catch(const ::ipp::IwException &) { m_ok = false; return; @@ -3291,7 +3291,7 @@ public: ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, m_dst.m_size.width, range.end - range.start); CV_INSTRUMENT_FUN_IPP(iwiWarpAffine, m_src, m_dst, tile); } - catch(::ipp::IwException) + catch(const ::ipp::IwException &) { m_ok = false; return; @@ -3387,7 +3387,7 @@ static bool ipp_resize(const uchar * src_data, size_t src_step, int src_width, i if(!ok) return false; } - catch(::ipp::IwException) + catch(const ::ipp::IwException &) { return false; } diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index f327d9f067..3eb79594fe 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1510,7 +1510,7 @@ static bool ipp_boxfilter(Mat &src, Mat &dst, Size ksize, Point anchor, bool nor CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBox, iwSrc, iwDst, iwKSize, ::ipp::IwDefault(), ippBorder); } - catch (::ipp::IwException) + catch (const ::ipp::IwException &) { return false; } @@ -4000,7 +4000,7 @@ public: ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, m_dst.m_size.width, range.end - range.start); CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterGaussian, m_src, m_dst, m_kernelSize, m_sigma, ::ipp::IwDefault(), m_border, tile); } - catch(::ipp::IwException e) + catch(const ::ipp::IwException &) { *m_pOk = false; return; @@ -4067,7 +4067,7 @@ static bool ipp_GaussianBlur(InputArray _src, OutputArray _dst, Size ksize, CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterGaussian, iwSrc, iwDst, ksize.width, sigma1, ::ipp::IwDefault(), ippBorder); } } - catch (::ipp::IwException ex) + catch (const ::ipp::IwException &) { return false; } @@ -5878,7 +5878,7 @@ public: ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, dst.m_size.width, range.end - range.start); CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBilateral, src, dst, radius, valSquareSigma, posSquareSigma, ::ipp::IwDefault(), borderType, tile); } - catch(::ipp::IwException) + catch(const ::ipp::IwException &) { *pOk = false; return; @@ -5933,7 +5933,7 @@ static bool ipp_bilateralFilter(Mat &src, Mat &dst, int d, double sigmaColor, do CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBilateral, iwSrc, iwDst, radius, valSquareSigma, posSquareSigma, ::ipp::IwDefault(), ippBorder); } } - catch (::ipp::IwException) + catch (const ::ipp::IwException &) { return false; } From 5640b36f6de8f30068693ff451725dbd1da31fcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Tue, 16 Oct 2018 21:13:23 +0200 Subject: [PATCH 04/10] Remove unused empty block --- modules/videoio/src/cap_ffmpeg_impl.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index fb306c7fc7..26a9369993 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -1519,8 +1519,6 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo _opencv_ffmpeg_av_image_fill_arrays(picture, picture_buf, (AVPixelFormat) pix_fmt, width, height); } - else { - } return picture; } From 85b9960f621e9b90b39806e01b74afc2bb717d1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Tue, 16 Oct 2018 21:15:54 +0200 Subject: [PATCH 05/10] Fix clashing include guards Relevant guards can be found in https://github.com/opencv/opencv/blob/ef5579dc8667e5eb5e149acc4af898421eed99da/modules/features2d/src/kaze/AKAZEConfig.h#L8 and https://github.com/opencv/opencv/blob/ef5579dc8667e5eb5e149acc4af898421eed99da/modules/ml/include/opencv2/ml.hpp#L44 --- apps/traincascade/old_ml.hpp | 6 +++--- modules/features2d/src/kaze/KAZEConfig.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/traincascade/old_ml.hpp b/apps/traincascade/old_ml.hpp index 3ad739dd64..de3aa407a2 100644 --- a/apps/traincascade/old_ml.hpp +++ b/apps/traincascade/old_ml.hpp @@ -38,8 +38,8 @@ // //M*/ -#ifndef OPENCV_ML_HPP -#define OPENCV_ML_HPP +#ifndef OPENCV_OLD_ML_HPP +#define OPENCV_OLD_ML_HPP #ifdef __cplusplus # include "opencv2/core.hpp" @@ -2037,6 +2037,6 @@ template<> void DefaultDeleter::operator ()(CvDTreeSplit* obj) con } #endif // __cplusplus -#endif // OPENCV_ML_HPP +#endif // OPENCV_OLD_ML_HPP /* End of file. */ diff --git a/modules/features2d/src/kaze/KAZEConfig.h b/modules/features2d/src/kaze/KAZEConfig.h index 5f2f8dcecd..3a7d6f8b7f 100644 --- a/modules/features2d/src/kaze/KAZEConfig.h +++ b/modules/features2d/src/kaze/KAZEConfig.h @@ -5,8 +5,8 @@ * @author Pablo F. Alcantarilla */ -#ifndef __OPENCV_FEATURES_2D_AKAZE_CONFIG_H__ -#define __OPENCV_FEATURES_2D_AKAZE_CONFIG_H__ +#ifndef __OPENCV_FEATURES_2D_KAZE_CONFIG_H__ +#define __OPENCV_FEATURES_2D_KAZE_CONFIG_H__ // OpenCV Includes #include "../precomp.hpp" From 365451dab0a0f697eca0a5ca90ca019866704eda Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Wed, 17 Oct 2018 14:02:37 +0300 Subject: [PATCH 06/10] Implement getBatchSize for Intel's Inference Engine networks --- modules/dnn/src/op_inf_engine.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/modules/dnn/src/op_inf_engine.cpp b/modules/dnn/src/op_inf_engine.cpp index 23794a187d..ae837a7a0b 100644 --- a/modules/dnn/src/op_inf_engine.cpp +++ b/modules/dnn/src/op_inf_engine.cpp @@ -331,8 +331,18 @@ InferenceEngine::StatusCode InfEngineBackendNet::setBatchSize(size_t size, Infer size_t InfEngineBackendNet::getBatchSize() const noexcept { - CV_Error(Error::StsNotImplemented, ""); - return 0; + size_t batchSize = 0; + for (const auto& inp : inputs) + { + CV_Assert(inp.second); + std::vector dims = inp.second->getDims(); + CV_Assert(!dims.empty()); + if (batchSize != 0) + CV_Assert(batchSize == dims.back()); + else + batchSize = dims.back(); + } + return batchSize; } #if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2018R2) From 4d1f0ef2d9a6f1c8df828c9d6528ba3b764868e4 Mon Sep 17 00:00:00 2001 From: Mansoo Kim Date: Wed, 17 Oct 2018 17:35:40 +0000 Subject: [PATCH 07/10] cuda: fix build with CUDA 10.x --- modules/core/include/opencv2/core/types_c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/include/opencv2/core/types_c.h b/modules/core/include/opencv2/core/types_c.h index 9ee8c9d2b6..d4216e0df4 100644 --- a/modules/core/include/opencv2/core/types_c.h +++ b/modules/core/include/opencv2/core/types_c.h @@ -1353,7 +1353,7 @@ CvSlice; CV_INLINE CvSlice cvSlice( int start, int end ) { -#if !(defined(CV__ENABLE_C_API_CTORS) && defined(__cplusplus)) +#if !(defined(CV__ENABLE_C_API_CTORS) && defined(__cplusplus) && !defined(__CUDACC__)) CvSlice slice = { start, end }; #else CvSlice slice(start, end); From a7dfa261d85981a7a4b330fbc6d422f52d88948c Mon Sep 17 00:00:00 2001 From: Apoorv Date: Thu, 18 Oct 2018 04:09:16 +0530 Subject: [PATCH 08/10] Add documentation for radiusSearch --- modules/flann/include/opencv2/flann.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/modules/flann/include/opencv2/flann.hpp b/modules/flann/include/opencv2/flann.hpp index 22c6ffcf19..c72693d34e 100644 --- a/modules/flann/include/opencv2/flann.hpp +++ b/modules/flann/include/opencv2/flann.hpp @@ -217,6 +217,17 @@ public: std::vector& dists, int knn, const ::cvflann::SearchParams& params); void knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& params); + /** @brief Performs a radius nearest neighbor search for a given query point using the index. + + @param query The query point. + @param indices Vector that will contain the indices of the nearest neighbors found. + @param dists Vector that will contain the distances to the nearest neighbors found. It has the same + number of elements as indices. + @param radius The search radius. + @param params SearchParams + + This function returns the number of nearest neighbors found. + */ int radiusSearch(const std::vector& query, std::vector& indices, std::vector& dists, DistanceType radius, const ::cvflann::SearchParams& params); int radiusSearch(const Mat& query, Mat& indices, Mat& dists, From e7015f6ae872b2ca2260d4387d74731ef9dc26f8 Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Fri, 19 Oct 2018 17:43:26 +0300 Subject: [PATCH 09/10] Fix ENet test --- modules/dnn/test/test_torch_importer.cpp | 46 ++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/modules/dnn/test/test_torch_importer.cpp b/modules/dnn/test/test_torch_importer.cpp index dd7d975af6..0b844452e2 100644 --- a/modules/dnn/test/test_torch_importer.cpp +++ b/modules/dnn/test/test_torch_importer.cpp @@ -287,6 +287,46 @@ TEST_P(Test_Torch_nets, OpenFace_accuracy) normAssert(out, outRef, "", default_l1, default_lInf); } +static Mat getSegmMask(const Mat& scores) +{ + const int rows = scores.size[2]; + const int cols = scores.size[3]; + const int numClasses = scores.size[1]; + + Mat maxCl = Mat::zeros(rows, cols, CV_8UC1); + Mat maxVal(rows, cols, CV_32FC1, Scalar(0)); + for (int ch = 0; ch < numClasses; ch++) + { + for (int row = 0; row < rows; row++) + { + const float *ptrScore = scores.ptr(0, ch, row); + uint8_t *ptrMaxCl = maxCl.ptr(row); + float *ptrMaxVal = maxVal.ptr(row); + for (int col = 0; col < cols; col++) + { + if (ptrScore[col] > ptrMaxVal[col]) + { + ptrMaxVal[col] = ptrScore[col]; + ptrMaxCl[col] = (uchar)ch; + } + } + } + } + return maxCl; +} + +// Computer per-class intersection over union metric. +static void normAssertSegmentation(const Mat& ref, const Mat& test) +{ + CV_Assert_N(ref.dims == 4, test.dims == 4); + const int numClasses = ref.size[1]; + CV_Assert(numClasses == test.size[1]); + + Mat refMask = getSegmMask(ref); + Mat testMask = getSegmMask(test); + EXPECT_EQ(countNonZero(refMask != testMask), 0); +} + TEST_P(Test_Torch_nets, ENet_accuracy) { checkBackend(); @@ -313,14 +353,16 @@ TEST_P(Test_Torch_nets, ENet_accuracy) // Due to numerical instability in Pooling-Unpooling layers (indexes jittering) // thresholds for ENet must be changed. Accuracy of results was checked on // Cityscapes dataset and difference in mIOU with Torch is 10E-4% - normAssert(ref, out, "", 0.00044, /*target == DNN_TARGET_CPU ? 0.453 : */0.5); + normAssert(ref, out, "", 0.00044, /*target == DNN_TARGET_CPU ? 0.453 : */0.552); + normAssertSegmentation(ref, out); const int N = 3; for (int i = 0; i < N; i++) { net.setInput(inputBlob, ""); Mat out = net.forward(); - normAssert(ref, out, "", 0.00044, /*target == DNN_TARGET_CPU ? 0.453 : */0.5); + normAssert(ref, out, "", 0.00044, /*target == DNN_TARGET_CPU ? 0.453 : */0.552); + normAssertSegmentation(ref, out); } } From d8ffddd07589f29371c324066352d6938d02c2c5 Mon Sep 17 00:00:00 2001 From: Apoorv Goel <35146783+UnderscoreAsterisk@users.noreply.github.com> Date: Sat, 20 Oct 2018 13:45:13 +0530 Subject: [PATCH 10/10] Merge pull request #12871 from UnderscoreAsterisk:document-Distance * Document distance functors in dist.h * Add spec for Distance * Generate appropriate links for symbols --- modules/flann/include/opencv2/flann.hpp | 52 +++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/modules/flann/include/opencv2/flann.hpp b/modules/flann/include/opencv2/flann.hpp index c72693d34e..fec3d067c8 100644 --- a/modules/flann/include/opencv2/flann.hpp +++ b/modules/flann/include/opencv2/flann.hpp @@ -103,6 +103,58 @@ using ::cvflann::KL_Divergence; /** @brief The FLANN nearest neighbor index class. This class is templated with the type of elements for which the index is built. + +`Distance` functor specifies the metric to be used to calculate the distance between two points. +There are several `Distance` functors that are readily available: + +@link cvflann::L2_Simple cv::flann::L2_Simple @endlink- Squared Euclidean distance functor. +This is the simpler, unrolled version. This is preferable for very low dimensionality data (eg 3D points) + +@link cvflann::L2 cv::flann::L2 @endlink- Squared Euclidean distance functor, optimized version. + +@link cvflann::L1 cv::flann::L1 @endlink - Manhattan distance functor, optimized version. + +@link cvflann::MinkowskiDistance cv::flann::MinkowskiDistance @endlink - The Minkowsky distance functor. +This is highly optimised with loop unrolling. +The computation of squared root at the end is omitted for efficiency. + +@link cvflann::MaxDistance cv::flann::MaxDistance @endlink - The max distance functor. It computes the +maximum distance between two vectors. This distance is not a valid kdtree distance, it's not +dimensionwise additive. + +@link cvflann::HammingLUT cv::flann::HammingLUT @endlink - %Hamming distance functor. It counts the bit +differences between two strings using a lookup table implementation. + +@link cvflann::Hamming cv::flann::Hamming @endlink - %Hamming distance functor. Population count is +performed using library calls, if available. Lookup table implementation is used as a fallback. + +@link cvflann::Hamming2 cv::flann::Hamming2 @endlink- %Hamming distance functor. Population count is +implemented in 12 arithmetic operations (one of which is multiplication). + +@link cvflann::HistIntersectionDistance cv::flann::HistIntersectionDistance @endlink - The histogram +intersection distance functor. + +@link cvflann::HellingerDistance cv::flann::HellingerDistance @endlink - The Hellinger distance functor. + +@link cvflann::ChiSquareDistance cv::flann::ChiSquareDistance @endlink - The chi-square distance functor. + +@link cvflann::KL_Divergence cv::flann::KL_Divergence @endlink - The Kullback-Leibler divergence functor. + +Although the provided implementations cover a vast range of cases, it is also possible to use +a custom implementation. The distance functor is a class whose `operator()` computes the distance +between two features. If the distance is also a kd-tree compatible distance, it should also provide an +`accum_dist()` method that computes the distance between individual feature dimensions. + +In addition to `operator()` and `accum_dist()`, a distance functor should also define the +`ElementType` and the `ResultType` as the types of the elements it operates on and the type of the +result it computes. If a distance functor can be used as a kd-tree distance (meaning that the full +distance between a pair of features can be accumulated from the partial distances between the +individual dimensions) a typedef `is_kdtree_distance` should be present inside the distance functor. +If the distance is not a kd-tree distance, but it's a distance in a vector space (the individual +dimensions of the elements it operates on can be accessed independently) a typedef +`is_vector_space_distance` should be defined inside the functor. If neither typedef is defined, the +distance is assumed to be a metric distance and will only be used with indexes operating on +generic metric distances. */ template class GenericIndex