Commit d6832ad69f47fab2f05b1e715df805d37bfb0dc2

Authored by bhklein
Committed by Scott Klum
1 parent 608cb6b1

Allow user specification of evaluation range, sample FRR at fixed values

openbr/core/eval.cpp
@@ -134,17 +134,17 @@ static cv::Mat constructMatchingMask(const cv::Mat &scores, const FileList &targ @@ -134,17 +134,17 @@ static cv::Mat constructMatchingMask(const cv::Mat &scores, const FileList &targ
134 return cv::Mat(); 134 return cv::Mat();
135 } 135 }
136 136
137 -float Evaluate(const cv::Mat &scores, const FileList &target, const FileList &query, const QString &csv, int partition) 137 +float Evaluate(const cv::Mat &scores, const FileList &target, const FileList &query, const File &csv, int partition)
138 { 138 {
139 return Evaluate(scores, constructMatchingMask(scores, target, query, partition), csv, QString(), QString(), 0); 139 return Evaluate(scores, constructMatchingMask(scores, target, query, partition), csv, QString(), QString(), 0);
140 } 140 }
141 141
142 -float Evaluate(const QString &simmat, const QString &mask, const QString &csv, unsigned int matches) 142 +float Evaluate(const QString &simmat, const QString &mask, const File &csv, unsigned int matches)
143 { 143 {
144 qDebug("Evaluating %s%s%s", 144 qDebug("Evaluating %s%s%s",
145 qPrintable(simmat), 145 qPrintable(simmat),
146 mask.isEmpty() ? "" : qPrintable(" with " + mask), 146 mask.isEmpty() ? "" : qPrintable(" with " + mask),
147 - csv.isEmpty() ? "" : qPrintable(" to " + csv)); 147 + csv.name.isEmpty() ? "" : qPrintable(" to " + csv));
148 148
149 // Read similarity matrix 149 // Read similarity matrix
150 QString target, query; 150 QString target, query;
@@ -176,7 +176,7 @@ float Evaluate(const QString &simmat, const QString &mask, const QString &csv, u @@ -176,7 +176,7 @@ float Evaluate(const QString &simmat, const QString &mask, const QString &csv, u
176 return Evaluate(scores, truth, csv, target, query, matches); 176 return Evaluate(scores, truth, csv, target, query, matches);
177 } 177 }
178 178
179 -float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv, const QString &target, const QString &query, unsigned int matches) 179 +float Evaluate(const Mat &simmat, const Mat &mask, const File &csv, const QString &target, const QString &query, unsigned int matches)
180 { 180 {
181 if (target.isEmpty() || query.isEmpty()) matches = 0; 181 if (target.isEmpty() || query.isEmpty()) matches = 0;
182 if (simmat.size() != mask.size()) 182 if (simmat.size() != mask.size())
@@ -232,7 +232,7 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv, const QSt @@ -232,7 +232,7 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv, const QSt
232 if (numNaNs > 0) qWarning("Encountered %d NaN scores!", numNaNs); 232 if (numNaNs > 0) qWarning("Encountered %d NaN scores!", numNaNs);
233 if (genuineCount == 0) qFatal("No genuine scores!"); 233 if (genuineCount == 0) qFatal("No genuine scores!");
234 if (impostorCount == 0) qFatal("No impostor scores!"); 234 if (impostorCount == 0) qFatal("No impostor scores!");
235 - if (totalImpostorSearches == 0) totalImpostorSearches = 1; 235 + if (totalImpostorSearches == 0) totalImpostorSearches = 10;
236 236
237 // Sort comparisons by simmat_val (score) 237 // Sort comparisons by simmat_val (score)
238 std::stable_sort(comparisons.begin(), comparisons.end()); 238 std::stable_sort(comparisons.begin(), comparisons.end());
@@ -346,33 +346,31 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv, const QSt @@ -346,33 +346,31 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv, const QSt
346 } 346 }
347 } 347 }
348 348
349 - // Write Detection Error Tradeoff (DET), PRE, REC  
350 - float expFAR = ceil(log10(impostorCount)); 349 + // Write Detection Error Tradeoff (DET), PRE, REC, Identification Error Tradeoff (IET)
  350 + float expFAR = csv.get<float>("FAR", ceil(log10(impostorCount)));
  351 + float expFRR = csv.get<float>("FRR", ceil(log10(genuineCount)));
  352 + float expFPIR = csv.get<float>("FPIR", ceil(log10(totalImpostorSearches)));
  353 +
351 float FARstep = expFAR / (float)(Max_Points - 1); 354 float FARstep = expFAR / (float)(Max_Points - 1);
352 - for (float i = -expFAR; i <= 0; i += FARstep) {  
353 - float FAR = pow(10, i);  
354 - OperatingPoint operatingPoint = getOperatingPointGivenFAR(operatingPoints, FAR); 355 + float FRRstep = expFRR / (float)(Max_Points - 1);
  356 + float FPIRstep = expFPIR / (float)(Max_Points - 1);
  357 +
  358 + for (int i=0; i<Max_Points; i++) {
  359 + float FAR = pow(10, -expFAR + i*FARstep);
  360 + float FRR = pow(10, -expFRR + i*FRRstep);
  361 + float FPIR = pow(10, -expFPIR + i*FPIRstep);
  362 +
  363 + OperatingPoint operatingPointFAR = getOperatingPointGivenFAR(operatingPoints, FAR);
  364 + OperatingPoint operatingPointTAR = getOperatingPointGivenTAR(operatingPoints, 1-FRR);
  365 + OperatingPoint searchOperatingPoint = getOperatingPointGivenFAR(searchOperatingPoints, FPIR);
355 lines.append(QString("DET,%1,%2").arg(QString::number(FAR), 366 lines.append(QString("DET,%1,%2").arg(QString::number(FAR),
356 - QString::number(1-operatingPoint.TAR)));  
357 - lines.append(QString("FAR,%1,%2").arg(QString::number(operatingPoint.score), 367 + QString::number(1-operatingPointFAR.TAR)));
  368 + lines.append(QString("FAR,%1,%2").arg(QString::number(operatingPointFAR.score),
358 QString::number(FAR))); 369 QString::number(FAR)));
359 - lines.append(QString("FRR,%1,%2").arg(QString::number(operatingPoint.score),  
360 - QString::number(1-operatingPoint.TAR)));  
361 - }  
362 -  
363 - // Write Identification Error Tradeoff (IET)  
364 - float expFPIR = ceil(log10(totalImpostorSearches));  
365 - if (expFPIR > 1) {  
366 - float FPIRstep = expFPIR / (float)(Max_Points - 1);  
367 - for (float i = -expFPIR; i <= 0; i += FPIRstep) {  
368 - float FPIR = pow(10, i);  
369 - OperatingPoint searchOperatingPoint = getOperatingPointGivenFAR(searchOperatingPoints, FPIR);  
370 - lines.append(QString("IET,%1,%2").arg(QString::number(searchOperatingPoint.FAR), 370 + lines.append(QString("FRR,%1,%2").arg(QString::number(operatingPointTAR.score),
  371 + QString::number(FRR)));
  372 + lines.append(QString("IET,%1,%2").arg(QString::number(searchOperatingPoint.FAR),
371 QString::number(1-searchOperatingPoint.TAR))); 373 QString::number(1-searchOperatingPoint.TAR)));
372 - }  
373 - } else {  
374 - lines.append(QString("IET,%1,%2").arg(QString::number(1), QString::number(1)));  
375 - lines.append(QString("IET,%1,%2").arg(QString::number(0), QString::number(0)));  
376 } 374 }
377 375
378 // Write TAR@FAR Table (TF) 376 // Write TAR@FAR Table (TF)
openbr/core/eval.h
@@ -23,9 +23,9 @@ @@ -23,9 +23,9 @@
23 23
24 namespace br 24 namespace br
25 { 25 {
26 - float Evaluate(const QString &simmat, const QString &mask = "", const QString &csv = "", unsigned int matches = 0); // Returns TAR @ FAR = 0.001  
27 - float Evaluate(const cv::Mat &scores, const FileList &target, const FileList &query, const QString &csv = "", int parition = 0);  
28 - float Evaluate(const cv::Mat &scores, const cv::Mat &masks, const QString &csv = "", const QString &target = "", const QString &query = "", unsigned int matches = 0); 26 + float Evaluate(const QString &simmat, const QString &mask = "", const File &csv = "", unsigned int matches = 0); // Returns TAR @ FAR = 0.001
  27 + float Evaluate(const cv::Mat &scores, const FileList &target, const FileList &query, const File &csv = "", int parition = 0);
  28 + float Evaluate(const cv::Mat &scores, const cv::Mat &masks, const File &csv = "", const QString &target = "", const QString &query = "", unsigned int matches = 0);
29 void assertEval(const QString &simmat, const QString &mask, float accuracy); // Check to see if -eval achieves a given TAR @ FAR = 0.001 29 void assertEval(const QString &simmat, const QString &mask, float accuracy); // Check to see if -eval achieves a given TAR @ FAR = 0.001
30 float InplaceEval(const QString & simmat, const QString & target, const QString & query, const QString & csv = ""); 30 float InplaceEval(const QString & simmat, const QString & target, const QString & query, const QString & csv = "");
31 31
openbr/core/plot.cpp
@@ -381,7 +381,7 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show) @@ -381,7 +381,7 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show)
381 (p.minor.size > 1 ? QString(" + facet_grid(%2 ~ X)").arg(p.minor.header) : QString(" + facet_grid(. ~ X, labeller=far_labeller)")) + 381 (p.minor.size > 1 ? QString(" + facet_grid(%2 ~ X)").arg(p.minor.header) : QString(" + facet_grid(. ~ X, labeller=far_labeller)")) +
382 QString(" + scale_y_continuous(labels=percent) + theme(legend.position=\"none\", axis.text.x=element_text(angle=-90, hjust=0))%1").arg((p.major.smooth || p.minor.smooth) ? "" : " + geom_text(data=BC, aes(label=Y, y=0.05))") + "\n\n")); 382 QString(" + scale_y_continuous(labels=percent) + theme(legend.position=\"none\", axis.text.x=element_text(angle=-90, hjust=0))%1").arg((p.major.smooth || p.minor.smooth) ? "" : " + geom_text(data=BC, aes(label=Y, y=0.05))") + "\n\n"));
383 383
384 - p.file.write(qPrintable(QString("qplot(X, Y, data=ERR%1, linetype=Error").arg((p.major.smooth || p.minor.smooth) ? ", geom=\"smooth\", method=loess, level=0.99" : ", geom=\"line\"") + 384 + p.file.write(qPrintable(QString("qplot(X, Y, data=ERR, geom=\"line\", linetype=Error") +
385 ((p.flip ? p.major.size : p.minor.size) > 1 ? QString(", colour=factor(%1)").arg(p.flip ? p.major.header : p.minor.header) : QString()) + 385 ((p.flip ? p.major.size : p.minor.size) > 1 ? QString(", colour=factor(%1)").arg(p.flip ? p.major.header : p.minor.header) : QString()) +
386 QString(", xlab=\"Score\", ylab=\"Error Rate\") + theme_minimal()") + 386 QString(", xlab=\"Score\", ylab=\"Error Rate\") + theme_minimal()") +
387 ((p.flip ? p.major.size : p.minor.size) > 1 ? getScale("colour", p.flip ? p.major.header : p.minor.header, p.flip ? p.major.size : p.minor.size) : QString()) + 387 ((p.flip ? p.major.size : p.minor.size) > 1 ? getScale("colour", p.flip ? p.major.header : p.minor.header, p.flip ? p.major.size : p.minor.size) : QString()) +