Commit 89b9823b24a1fd933aeb8c2e3f16024eeb07ba85

Authored by Josh Klontz
1 parent 8b418541

generalized -evalDetection

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