Commit d61c72e9f96b5ba3d4e2ed30e6f6b8ffff1968d5

Authored by Josh Klontz
2 parents 83943217 89b9823b

Merge pull request #182 from biometrics/evalDetection

generalized -evalDetection
Showing 1 changed file with 64 additions and 42 deletions
openbr/core/eval.cpp
... ... @@ -433,84 +433,106 @@ static QStringList computeDetectionResults(const QList<ResolvedDetection> &detec
433 433 return lines;
434 434 }
435 435  
436   -QString getDetectKey(const TemplateList &templates)
  436 +struct DetectionKey : public QString
437 437 {
438   - const File &f = templates.first().file;
439   - foreach (const QString &key, f.localKeys()) {
440   - // first check for single detections
  438 + enum Type {
  439 + Invalid,
  440 + Rect,
  441 + RectList,
  442 + XYWidthHeight
  443 + } type;
  444 +
  445 + DetectionKey(const QString &key = "", Type type = Invalid)
  446 + : QString(key), type(type) {}
  447 +};
  448 +
  449 +static DetectionKey getDetectKey(const FileList &files)
  450 +{
  451 + if (files.empty())
  452 + return DetectionKey();
  453 +
  454 + const File &f = files.first();
  455 + const QStringList localKeys = f.localKeys();
  456 +
  457 + // first check for single detections
  458 + foreach (const QString &key, localKeys)
441 459 if (!f.get<QRectF>(key, QRectF()).isNull())
442   - return key;
443   - }
  460 + return DetectionKey(key, DetectionKey::Rect);
  461 +
444 462 // and then multiple
445 463 if (!f.rects().empty())
446   - return "Rects";
447   - return "";
448   -}
  464 + return DetectionKey("Rects", DetectionKey::RectList);
449 465  
450   -bool detectKeyIsList(QString key, const TemplateList &templates)
451   -{
452   - return templates.first().file.get<QRectF>(key, QRectF()).isNull();
  466 + // check for <Key>_X, <Key>_Y, <Key>_Width, <Key>_Height
  467 + foreach (const QString &localKey, localKeys) {
  468 + if (!localKey.endsWith("_X"))
  469 + continue;
  470 + const QString key = localKey.mid(0, localKey.size()-2);
  471 + if (localKeys.contains(key+"_Y") &&
  472 + localKeys.contains(key+"_Width") &&
  473 + localKeys.contains(key+"_Height"))
  474 + return DetectionKey(key, DetectionKey::XYWidthHeight);
  475 + }
  476 +
  477 + return DetectionKey();
453 478 }
454 479  
455   -// return a list of detections whether the template holds
456   -// multiple detections or a single detection
457   -QList<Detection> getDetections(QString key, const Template &t, bool isList, bool isTruth)
  480 +// return a list of detections independent of the detection key format
  481 +static QList<Detection> getDetections(const DetectionKey &key, const File &f, bool isTruth)
458 482 {
459   - File f = t.file;
460 483 QList<Detection> dets;
461   - if (isList) {
  484 + if (key.type == DetectionKey::RectList) {
462 485 QList<QRectF> rects = f.rects();
463 486 QList<float> confidences = f.getList<float>("Confidences", QList<float>());
464 487 if (!isTruth && rects.size() != confidences.size())
465 488 qFatal("You don't have enough confidence. I mean, your detections don't all have confidence measures.");
466 489 for (int i=0; i<rects.size(); i++) {
467 490 if (isTruth)
468   - dets.append(Detection(rects.at(i)));
  491 + dets.append(Detection(rects[i]));
469 492 else
470   - dets.append(Detection(rects.at(i), confidences.at(i)));
  493 + dets.append(Detection(rects[i], confidences[i]));
471 494 }
472   - } else {
473   - if (isTruth)
474   - dets.append(Detection(f.get<QRectF>(key)));
475   - else
476   - dets.append(Detection(f.get<QRectF>(key), f.get<float>("Confidence", -1)));
  495 + } else if (key.type == DetectionKey::Rect) {
  496 + dets.append(Detection(f.get<QRectF>(key), isTruth ? -1 : f.get<float>("Confidence", -1)));
  497 + } else if (key.type == DetectionKey::XYWidthHeight) {
  498 + const QRectF rect(f.get<float>(key+"_X"), f.get<float>(key+"_Y"), f.get<float>(key+"_Width"), f.get<float>(key+"_Height"));
  499 + dets.append(Detection(rect, isTruth ? -1 : f.get<float>("Confidence", -1)));
477 500 }
478 501 return dets;
479 502 }
480 503  
481   -QMap<QString, Detections> getDetections(const TemplateList &predicted, const TemplateList &truth)
  504 +static QMap<QString, Detections> getDetections(const File &predictedGallery, const File &truthGallery)
482 505 {
  506 + const FileList predicted = TemplateList::fromGallery(predictedGallery).files();
  507 + const FileList truth = TemplateList::fromGallery(truthGallery).files();
  508 +
483 509 // Figure out which metadata field contains a bounding box
484   - QString truthDetectKey = getDetectKey(truth);
485   - if (truthDetectKey.isEmpty()) qFatal("No suitable ground truth metadata key found.");
486   - QString predictedDetectKey = getDetectKey(predicted);
487   - if (predictedDetectKey.isEmpty()) qFatal("No suitable predicted metadata key found.");
  510 + DetectionKey truthDetectKey = getDetectKey(truth);
  511 + if (truthDetectKey.isEmpty())
  512 + qFatal("No suitable ground truth metadata key found.");
  513 +
  514 + DetectionKey predictedDetectKey = getDetectKey(predicted);
  515 + if (predictedDetectKey.isEmpty())
  516 + qFatal("No suitable predicted metadata key found.");
  517 +
488 518 qDebug("Using metadata key: %s%s",
489 519 qPrintable(predictedDetectKey),
490 520 qPrintable(predictedDetectKey == truthDetectKey ? QString() : "/"+truthDetectKey));
491 521  
492 522 QMap<QString, Detections> allDetections;
493   - bool predKeyIsList = detectKeyIsList(predictedDetectKey, predicted);
494   - bool truthKeyIsList = detectKeyIsList(truthDetectKey, truth);
495   - foreach (const Template &t, predicted) {
496   - QList<Detection> dets = getDetections(predictedDetectKey, t, predKeyIsList, false);
497   - allDetections[t.file.baseName()].predicted.append(dets);
498   - }
499   - foreach (const Template &t, truth) {
500   - QList<Detection> dets = getDetections(truthDetectKey, t, truthKeyIsList, true);
501   - allDetections[t.file.baseName()].truth.append(dets);
502   - }
  523 + foreach (const File &f, predicted)
  524 + allDetections[f.baseName()].predicted.append(getDetections(predictedDetectKey, f, false));
  525 + foreach (const File &f, truth)
  526 + allDetections[f.baseName()].truth.append(getDetections(truthDetectKey, f, true));
503 527 return allDetections;
504 528 }
505 529  
506 530 float EvalDetection(const QString &predictedGallery, const QString &truthGallery, const QString &csv)
507 531 {
508 532 qDebug("Evaluating detection of %s against %s", qPrintable(predictedGallery), qPrintable(truthGallery));
509   - const TemplateList predicted(TemplateList::fromGallery(predictedGallery));
510   - const TemplateList truth(TemplateList::fromGallery(truthGallery));
511 533  
512 534 // Organized by file, QMap used to preserve order
513   - QMap<QString, Detections> allDetections = getDetections(predicted, truth);
  535 + QMap<QString, Detections> allDetections = getDetections(predictedGallery, truthGallery);
514 536  
515 537 QList<ResolvedDetection> resolvedDetections, falseNegativeDetections;
516 538 int totalTrueDetections = 0;
... ...