github.com/kaydxh/golang@v0.0.131/pkg/gocv/cgo/third_path/opencv4/include/opencv2/flann/index_testing.h (about) 1 /*********************************************************************** 2 * Software License Agreement (BSD License) 3 * 4 * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. 5 * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. 6 * 7 * THE BSD LICENSE 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 *************************************************************************/ 30 31 #ifndef OPENCV_FLANN_INDEX_TESTING_H_ 32 #define OPENCV_FLANN_INDEX_TESTING_H_ 33 34 //! @cond IGNORED 35 36 #include <cstring> 37 #include <cmath> 38 39 #include "matrix.h" 40 #include "nn_index.h" 41 #include "result_set.h" 42 #include "logger.h" 43 #include "timer.h" 44 45 46 namespace cvflann 47 { 48 49 inline int countCorrectMatches(int* neighbors, int* groundTruth, int n) 50 { 51 int count = 0; 52 for (int i=0; i<n; ++i) { 53 for (int k=0; k<n; ++k) { 54 if (neighbors[i]==groundTruth[k]) { 55 count++; 56 break; 57 } 58 } 59 } 60 return count; 61 } 62 63 64 template <typename Distance> 65 typename Distance::ResultType computeDistanceRaport(const Matrix<typename Distance::ElementType>& inputData, typename Distance::ElementType* target, 66 int* neighbors, int* groundTruth, int veclen, int n, const Distance& distance) 67 { 68 typedef typename Distance::ResultType DistanceType; 69 70 DistanceType ret = 0; 71 for (int i=0; i<n; ++i) { 72 DistanceType den = distance(inputData[groundTruth[i]], target, veclen); 73 DistanceType num = distance(inputData[neighbors[i]], target, veclen); 74 75 if ((den==0)&&(num==0)) { 76 ret += 1; 77 } 78 else { 79 ret += num/den; 80 } 81 } 82 83 return ret; 84 } 85 86 template <typename Distance> 87 float search_with_ground_truth(NNIndex<Distance>& index, const Matrix<typename Distance::ElementType>& inputData, 88 const Matrix<typename Distance::ElementType>& testData, const Matrix<int>& matches, int nn, int checks, 89 float& time, typename Distance::ResultType& dist, const Distance& distance, int skipMatches) 90 { 91 typedef typename Distance::ResultType DistanceType; 92 93 if (matches.cols<size_t(nn)) { 94 Logger::info("matches.cols=%d, nn=%d\n",matches.cols,nn); 95 96 FLANN_THROW(cv::Error::StsError, "Ground truth is not computed for as many neighbors as requested"); 97 } 98 99 KNNResultSet<DistanceType> resultSet(nn+skipMatches); 100 SearchParams searchParams(checks); 101 102 std::vector<int> indices(nn+skipMatches); 103 std::vector<DistanceType> dists(nn+skipMatches); 104 int* neighbors = &indices[skipMatches]; 105 106 int correct = 0; 107 DistanceType distR = 0; 108 StartStopTimer t; 109 int repeats = 0; 110 while (t.value<0.2) { 111 repeats++; 112 t.start(); 113 correct = 0; 114 distR = 0; 115 for (size_t i = 0; i < testData.rows; i++) { 116 resultSet.init(&indices[0], &dists[0]); 117 index.findNeighbors(resultSet, testData[i], searchParams); 118 119 correct += countCorrectMatches(neighbors,matches[i], nn); 120 distR += computeDistanceRaport<Distance>(inputData, testData[i], neighbors, matches[i], (int)testData.cols, nn, distance); 121 } 122 t.stop(); 123 } 124 time = float(t.value/repeats); 125 126 float precicion = (float)correct/(nn*testData.rows); 127 128 dist = distR/(testData.rows*nn); 129 130 Logger::info("%8d %10.4g %10.5g %10.5g %10.5g\n", 131 checks, precicion, time, 1000.0 * time / testData.rows, dist); 132 133 return precicion; 134 } 135 136 137 template <typename Distance> 138 float test_index_checks(NNIndex<Distance>& index, const Matrix<typename Distance::ElementType>& inputData, 139 const Matrix<typename Distance::ElementType>& testData, const Matrix<int>& matches, 140 int checks, float& precision, const Distance& distance, int nn = 1, int skipMatches = 0) 141 { 142 typedef typename Distance::ResultType DistanceType; 143 144 Logger::info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist\n"); 145 Logger::info("---------------------------------------------------------\n"); 146 147 float time = 0; 148 DistanceType dist = 0; 149 precision = search_with_ground_truth(index, inputData, testData, matches, nn, checks, time, dist, distance, skipMatches); 150 151 return time; 152 } 153 154 template <typename Distance> 155 float test_index_precision(NNIndex<Distance>& index, const Matrix<typename Distance::ElementType>& inputData, 156 const Matrix<typename Distance::ElementType>& testData, const Matrix<int>& matches, 157 float precision, int& checks, const Distance& distance, int nn = 1, int skipMatches = 0) 158 { 159 typedef typename Distance::ResultType DistanceType; 160 const float SEARCH_EPS = 0.001f; 161 162 Logger::info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist\n"); 163 Logger::info("---------------------------------------------------------\n"); 164 165 int c2 = 1; 166 float p2; 167 int c1 = 1; 168 //float p1; 169 float time; 170 DistanceType dist; 171 172 p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, distance, skipMatches); 173 174 if (p2>precision) { 175 Logger::info("Got as close as I can\n"); 176 checks = c2; 177 return time; 178 } 179 180 while (p2<precision) { 181 c1 = c2; 182 //p1 = p2; 183 c2 *=2; 184 p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, distance, skipMatches); 185 } 186 187 int cx; 188 float realPrecision; 189 if (fabs(p2-precision)>SEARCH_EPS) { 190 Logger::info("Start linear estimation\n"); 191 // after we got to values in the vecinity of the desired precision 192 // use linear approximation get a better estimation 193 194 cx = (c1+c2)/2; 195 realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, distance, skipMatches); 196 while (fabs(realPrecision-precision)>SEARCH_EPS) { 197 198 if (realPrecision<precision) { 199 c1 = cx; 200 } 201 else { 202 c2 = cx; 203 } 204 cx = (c1+c2)/2; 205 if (cx==c1) { 206 Logger::info("Got as close as I can\n"); 207 break; 208 } 209 realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, distance, skipMatches); 210 } 211 212 c2 = cx; 213 p2 = realPrecision; 214 215 } 216 else { 217 Logger::info("No need for linear estimation\n"); 218 cx = c2; 219 realPrecision = p2; 220 } 221 222 checks = cx; 223 return time; 224 } 225 226 227 template <typename Distance> 228 void test_index_precisions(NNIndex<Distance>& index, const Matrix<typename Distance::ElementType>& inputData, 229 const Matrix<typename Distance::ElementType>& testData, const Matrix<int>& matches, 230 float* precisions, int precisions_length, const Distance& distance, int nn = 1, int skipMatches = 0, float maxTime = 0) 231 { 232 typedef typename Distance::ResultType DistanceType; 233 234 const float SEARCH_EPS = 0.001; 235 236 // make sure precisions array is sorted 237 std::sort(precisions, precisions+precisions_length); 238 239 int pindex = 0; 240 float precision = precisions[pindex]; 241 242 Logger::info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist\n"); 243 Logger::info("---------------------------------------------------------\n"); 244 245 int c2 = 1; 246 float p2; 247 248 int c1 = 1; 249 float p1; 250 251 float time; 252 DistanceType dist; 253 254 p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, distance, skipMatches); 255 256 // if precision for 1 run down the tree is already 257 // better then some of the requested precisions, then 258 // skip those 259 while (precisions[pindex]<p2 && pindex<precisions_length) { 260 pindex++; 261 } 262 263 if (pindex==precisions_length) { 264 Logger::info("Got as close as I can\n"); 265 return; 266 } 267 268 for (int i=pindex; i<precisions_length; ++i) { 269 270 precision = precisions[i]; 271 while (p2<precision) { 272 c1 = c2; 273 p1 = p2; 274 c2 *=2; 275 p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, distance, skipMatches); 276 if ((maxTime> 0)&&(time > maxTime)&&(p2<precision)) return; 277 } 278 279 int cx; 280 float realPrecision; 281 if (fabs(p2-precision)>SEARCH_EPS) { 282 Logger::info("Start linear estimation\n"); 283 // after we got to values in the vecinity of the desired precision 284 // use linear approximation get a better estimation 285 286 cx = (c1+c2)/2; 287 realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, distance, skipMatches); 288 while (fabs(realPrecision-precision)>SEARCH_EPS) { 289 290 if (realPrecision<precision) { 291 c1 = cx; 292 } 293 else { 294 c2 = cx; 295 } 296 cx = (c1+c2)/2; 297 if (cx==c1) { 298 Logger::info("Got as close as I can\n"); 299 break; 300 } 301 realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, distance, skipMatches); 302 } 303 304 c2 = cx; 305 p2 = realPrecision; 306 307 } 308 else { 309 Logger::info("No need for linear estimation\n"); 310 cx = c2; 311 realPrecision = p2; 312 } 313 314 } 315 } 316 317 } 318 319 //! @endcond 320 321 #endif //OPENCV_FLANN_INDEX_TESTING_H_