00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef _OPENCV_TESTING_H_
00032 #define _OPENCV_TESTING_H_
00033
00034 #include <cstring>
00035 #include <cassert>
00036
00037 #include "opencv2/flann/matrix.h"
00038 #include "opencv2/flann/nn_index.h"
00039 #include "opencv2/flann/result_set.h"
00040 #include "opencv2/flann/logger.h"
00041 #include "opencv2/flann/timer.h"
00042
00043
00044 using namespace std;
00045
00046 namespace cvflann
00047 {
00048
00049 CV_EXPORTS int countCorrectMatches(int* neighbors, int* groundTruth, int n);
00050
00051
00052 template <typename ELEM_TYPE>
00053 float computeDistanceRaport(const Matrix<ELEM_TYPE>& inputData, ELEM_TYPE* target, int* neighbors, int* groundTruth, int veclen, int n)
00054 {
00055 ELEM_TYPE* target_end = target + veclen;
00056 float ret = 0;
00057 for (int i=0;i<n;++i) {
00058 float den = (float)flann_dist(target,target_end, inputData[groundTruth[i]]);
00059 float num = (float)flann_dist(target,target_end, inputData[neighbors[i]]);
00060
00061 if (den==0 && num==0) {
00062 ret += 1;
00063 }
00064 else {
00065 ret += num/den;
00066 }
00067 }
00068
00069 return ret;
00070 }
00071
00072 template <typename ELEM_TYPE>
00073 float search_with_ground_truth(NNIndex<ELEM_TYPE>& index, const Matrix<ELEM_TYPE>& inputData, const Matrix<ELEM_TYPE>& testData, const Matrix<int>& matches, int nn, int checks, float& time, float& dist, int skipMatches)
00074 {
00075 if (matches.cols<size_t(nn)) {
00076 logger().info("matches.cols=%d, nn=%d\n",matches.cols,nn);
00077
00078 throw FLANNException("Ground truth is not computed for as many neighbors as requested");
00079 }
00080
00081 KNNResultSet<ELEM_TYPE> resultSet(nn+skipMatches);
00082 SearchParams searchParams(checks);
00083
00084 int correct = 0;
00085 float distR = 0;
00086 StartStopTimer t;
00087 int repeats = 0;
00088 while (t.value<0.2) {
00089 repeats++;
00090 t.start();
00091 correct = 0;
00092 distR = 0;
00093 for (size_t i = 0; i < testData.rows; i++) {
00094 ELEM_TYPE* target = testData[i];
00095 resultSet.init(target, (int)testData.cols);
00096 index.findNeighbors(resultSet,target, searchParams);
00097 int* neighbors = resultSet.getNeighbors();
00098 neighbors = neighbors+skipMatches;
00099
00100 correct += countCorrectMatches(neighbors,matches[i], nn);
00101 distR += computeDistanceRaport(inputData, target,neighbors,matches[i], (int)testData.cols, nn);
00102 }
00103 t.stop();
00104 }
00105 time = (float)(t.value/repeats);
00106
00107
00108 float precicion = (float)correct/(nn*testData.rows);
00109
00110 dist = distR/(testData.rows*nn);
00111
00112 logger().info("%8d %10.4g %10.5g %10.5g %10.5g\n",
00113 checks, precicion, time, 1000.0 * time / testData.rows, dist);
00114
00115 return precicion;
00116 }
00117
00118
00119 template <typename ELEM_TYPE>
00120 float test_index_checks(NNIndex<ELEM_TYPE>& index, const Matrix<ELEM_TYPE>& inputData, const Matrix<ELEM_TYPE>& testData, const Matrix<int>& matches,
00121 int checks, float& precision, int nn = 1, int skipMatches = 0)
00122 {
00123 logger().info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist\n");
00124 logger().info("---------------------------------------------------------\n");
00125
00126 float time = 0;
00127 float dist = 0;
00128 precision = search_with_ground_truth(index, inputData, testData, matches, nn, checks, time, dist, skipMatches);
00129
00130 return time;
00131 }
00132
00133 template <typename ELEM_TYPE>
00134 float test_index_precision(NNIndex<ELEM_TYPE>& index, const Matrix<ELEM_TYPE>& inputData, const Matrix<ELEM_TYPE>& testData, const Matrix<int>& matches,
00135 float precision, int& checks, int nn = 1, int skipMatches = 0)
00136 {
00137 const float SEARCH_EPS = 0.001f;
00138
00139 logger().info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist\n");
00140 logger().info("---------------------------------------------------------\n");
00141
00142 int c2 = 1;
00143 float p2;
00144 int c1 = 1;
00145 float p1;
00146 float time;
00147 float dist;
00148
00149 p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, skipMatches);
00150
00151 if (p2>precision) {
00152 logger().info("Got as close as I can\n");
00153 checks = c2;
00154 return time;
00155 }
00156
00157 while (p2<precision) {
00158 c1 = c2;
00159 p1 = p2;
00160 c2 *=2;
00161 p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, skipMatches);
00162 }
00163
00164 int cx;
00165 float realPrecision;
00166 if (fabs(p2-precision)>SEARCH_EPS) {
00167 logger().info("Start linear estimation\n");
00168
00169
00170
00171 cx = (c1+c2)/2;
00172 realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, skipMatches);
00173 while (fabs(realPrecision-precision)>SEARCH_EPS) {
00174
00175 if (realPrecision<precision) {
00176 c1 = cx;
00177 }
00178 else {
00179 c2 = cx;
00180 }
00181 cx = (c1+c2)/2;
00182 if (cx==c1) {
00183 logger().info("Got as close as I can\n");
00184 break;
00185 }
00186 realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, skipMatches);
00187 }
00188
00189 c2 = cx;
00190 p2 = realPrecision;
00191
00192 } else {
00193 logger().info("No need for linear estimation\n");
00194 cx = c2;
00195 realPrecision = p2;
00196 }
00197
00198 checks = cx;
00199 return time;
00200 }
00201
00202
00203 template <typename ELEM_TYPE>
00204 float test_index_precisions(NNIndex<ELEM_TYPE>& index, const Matrix<ELEM_TYPE>& inputData, const Matrix<ELEM_TYPE>& testData, const Matrix<int>& matches,
00205 float* precisions, int precisions_length, int nn = 1, int skipMatches = 0, float maxTime = 0)
00206 {
00207 const float SEARCH_EPS = 0.001;
00208
00209
00210 sort(precisions, precisions+precisions_length);
00211
00212 int pindex = 0;
00213 float precision = precisions[pindex];
00214
00215 logger().info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist");
00216 logger().info("---------------------------------------------------------");
00217
00218 int c2 = 1;
00219 float p2;
00220
00221 int c1 = 1;
00222 float p1;
00223
00224 float time;
00225 float dist;
00226
00227 p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, skipMatches);
00228
00229
00230
00231
00232 while (precisions[pindex]<p2 && pindex<precisions_length) {
00233 pindex++;
00234 }
00235
00236 if (pindex==precisions_length) {
00237 logger().info("Got as close as I can\n");
00238 return time;
00239 }
00240
00241 for (int i=pindex;i<precisions_length;++i) {
00242
00243 precision = precisions[i];
00244 while (p2<precision) {
00245 c1 = c2;
00246 p1 = p2;
00247 c2 *=2;
00248 p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, skipMatches);
00249 if (maxTime> 0 && time > maxTime && p2<precision) return time;
00250 }
00251
00252 int cx;
00253 float realPrecision;
00254 if (fabs(p2-precision)>SEARCH_EPS) {
00255 logger().info("Start linear estimation\n");
00256
00257
00258
00259 cx = (c1+c2)/2;
00260 realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, skipMatches);
00261 while (fabs(realPrecision-precision)>SEARCH_EPS) {
00262
00263 if (realPrecision<precision) {
00264 c1 = cx;
00265 }
00266 else {
00267 c2 = cx;
00268 }
00269 cx = (c1+c2)/2;
00270 if (cx==c1) {
00271 logger().info("Got as close as I can\n");
00272 break;
00273 }
00274 realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, skipMatches);
00275 }
00276
00277 c2 = cx;
00278 p2 = realPrecision;
00279
00280 } else {
00281 logger().info("No need for linear estimation\n");
00282 cx = c2;
00283 realPrecision = p2;
00284 }
00285
00286 }
00287 return time;
00288 }
00289
00290 }
00291
00292 #endif //_OPENCV_TESTING_H_