Commit bddd6a348b466134572ecfc445edc5552bed1926

Authored by JordanCheney
Committed by GitHub
2 parents 34953f33 a4c49511

Merge pull request #583 from biometrics/object_eval

Add the ability to match object labels in the detection evaluation
app/br/br.cpp
@@ -160,8 +160,8 @@ public: @@ -160,8 +160,8 @@ public:
160 check((parc >= 2) && (parc <= 5), "Incorrect parameter count for 'evalClustering'."); 160 check((parc >= 2) && (parc <= 5), "Incorrect parameter count for 'evalClustering'.");
161 br_eval_clustering(parv[0], parv[1], parc > 2 ? parv[2] : "", parc > 3 ? atoi(parv[3]) : 1, parc > 4 ? parv[4] : ""); 161 br_eval_clustering(parv[0], parv[1], parc > 2 ? parv[2] : "", parc > 3 ? atoi(parv[3]) : 1, parc > 4 ? parv[4] : "");
162 } else if (!strcmp(fun, "evalDetection")) { 162 } else if (!strcmp(fun, "evalDetection")) {
163 - check((parc >= 2) && (parc <= 7), "Incorrect parameter count for 'evalDetection'.");  
164 - br_eval_detection(parv[0], parv[1], parc >= 3 ? parv[2] : "", parc >= 4 ? atoi(parv[3]) : 0, parc >= 5 ? atoi(parv[4]) : 0, parc >= 6 ? atoi(parv[5]) : 0, parc >= 7 ? atof(parv[6]) : 0); 163 + check((parc >= 2) && (parc <= 8), "Incorrect parameter count for 'evalDetection'.");
  164 + br_eval_detection(parv[0], parv[1], parc >= 3 ? parv[2] : "", parc >= 4 ? atoi(parv[3]) : 0, parc >= 5 ? atoi(parv[4]) : 0, parc >= 6 ? atoi(parv[5]) : 0, parc >= 7 ? atof(parv[6]) : 0, parc >= 8 ? parv[7] : "");
165 } else if (!strcmp(fun, "evalLandmarking")) { 165 } else if (!strcmp(fun, "evalLandmarking")) {
166 check((parc >= 2) && (parc <= 7), "Incorrect parameter count for 'evalLandmarking'."); 166 check((parc >= 2) && (parc <= 7), "Incorrect parameter count for 'evalLandmarking'.");
167 br_eval_landmarking(parv[0], parv[1], parc >= 3 ? parv[2] : "", parc >= 4 ? atoi(parv[3]) : 0, parc >= 5 ? atoi(parv[4]) : 1, parc >= 6 ? atoi(parv[5]) : 0, parc >= 7 ? atoi(parv[6]) : 5); 167 br_eval_landmarking(parv[0], parv[1], parc >= 3 ? parv[2] : "", parc >= 4 ? atoi(parv[3]) : 0, parc >= 5 ? atoi(parv[4]) : 1, parc >= 6 ? atoi(parv[5]) : 0, parc >= 7 ? atoi(parv[6]) : 5);
@@ -290,7 +290,7 @@ private: @@ -290,7 +290,7 @@ private:
290 "-convert (Format|Gallery|Output) <input_file> {output_file}\n" 290 "-convert (Format|Gallery|Output) <input_file> {output_file}\n"
291 "-evalClassification <predicted_gallery> <truth_gallery> <predicted property name> <ground truth proprty name>\n" 291 "-evalClassification <predicted_gallery> <truth_gallery> <predicted property name> <ground truth proprty name>\n"
292 "-evalClustering <clusters> <truth_gallery> [truth_property [cluster_csv [cluster_property]]]\n" 292 "-evalClustering <clusters> <truth_gallery> [truth_property [cluster_csv [cluster_property]]]\n"
293 - "-evalDetection <predicted_gallery> <truth_gallery> [{csv}] [{normalize}] [{minSize}] [{maxSize}]\n" 293 + "-evalDetection <predicted_gallery> <truth_gallery> [{csv}] [{normalize}] [{minSize}] [{maxSize}] [{label_filter}]\n"
294 "-evalLandmarking <predicted_gallery> <truth_gallery> [{csv} [<normalization_index_a> <normalization_index_b>] [sample_index] [total_examples]]\n" 294 "-evalLandmarking <predicted_gallery> <truth_gallery> [{csv} [<normalization_index_a> <normalization_index_b>] [sample_index] [total_examples]]\n"
295 "-evalRegression <predicted_gallery> <truth_gallery> <predicted property name> <ground truth property name>\n" 295 "-evalRegression <predicted_gallery> <truth_gallery> <predicted property name> <ground truth property name>\n"
296 "-evalKNN <knn_graph> <knn_truth> [{csv}]\n" 296 "-evalKNN <knn_graph> <knn_truth> [{csv}]\n"
openbr/core/eval.cpp
@@ -769,7 +769,7 @@ void EvalClassification(const QString &amp;predictedGallery, const QString &amp;truthGal @@ -769,7 +769,7 @@ void EvalClassification(const QString &amp;predictedGallery, const QString &amp;truthGal
769 qDebug("Overall Accuracy = %f", (float)tpc / (float)(tpc + fnc)); 769 qDebug("Overall Accuracy = %f", (float)tpc / (float)(tpc + fnc));
770 } 770 }
771 771
772 -float EvalDetection(const QString &predictedGallery, const QString &truthGallery, const QString &csv, bool normalize, int minSize, int maxSize, float relativeMinSize) 772 +float EvalDetection(const QString &predictedGallery, const QString &truthGallery, const QString &csv, bool normalize, int minSize, int maxSize, float relativeMinSize, const QString &label)
773 { 773 {
774 qDebug("Evaluating detection of %s against %s", qPrintable(predictedGallery), qPrintable(truthGallery)); 774 qDebug("Evaluating detection of %s against %s", qPrintable(predictedGallery), qPrintable(truthGallery));
775 // Organized by file, QMap used to preserve order 775 // Organized by file, QMap used to preserve order
@@ -789,6 +789,15 @@ float EvalDetection(const QString &amp;predictedGallery, const QString &amp;truthGallery @@ -789,6 +789,15 @@ float EvalDetection(const QString &amp;predictedGallery, const QString &amp;truthGallery
789 allDetections = filterDetections(allDetections, maxSize, false); 789 allDetections = filterDetections(allDetections, maxSize, false);
790 } 790 }
791 791
  792 + // Optionally, keep only detections with a specific label
  793 + if (!label.isEmpty()) {
  794 + if (Globals->verbose)
  795 + qDebug("Removing detections without label %s\n", qPrintable(label));
  796 + allDetections = filterLabels(allDetections, label);
  797 + if (allDetections.isEmpty())
  798 + qFatal("No detections left after filtering on label. Check your filter");
  799 + }
  800 +
792 QList<ResolvedDetection> resolvedDetections, falseNegativeDetections; 801 QList<ResolvedDetection> resolvedDetections, falseNegativeDetections;
793 QRectF normalizations(0, 0, 0, 0); 802 QRectF normalizations(0, 0, 0, 0);
794 803
openbr/core/eval.h
@@ -30,7 +30,7 @@ namespace br @@ -30,7 +30,7 @@ namespace br
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
32 void EvalClassification(const QString &predictedGallery, const QString &truthGallery, QString predictedProperty = "", QString truthProperty = ""); 32 void EvalClassification(const QString &predictedGallery, const QString &truthGallery, QString predictedProperty = "", QString truthProperty = "");
33 - float EvalDetection(const QString &predictedGallery, const QString &truthGallery, const QString &csv = "", bool normalize = false, int minSize = 0, int maxSize = 0, float relativeMinSize = 0); // Return average overlap 33 + float EvalDetection(const QString &predictedGallery, const QString &truthGallery, const QString &csv = "", bool normalize = false, int minSize = 0, int maxSize = 0, float relativeMinSize = 0, const QString &label = ""); // Return average overlap
34 float EvalLandmarking(const QString &predictedGallery, const QString &truthGallery, const QString &csv = "", int normalizationIndexA = 0, int normalizationIndexB = 1, int sampleIndex = 0, int totalExamples = 5); // Return average error 34 float EvalLandmarking(const QString &predictedGallery, const QString &truthGallery, const QString &csv = "", int normalizationIndexA = 0, int normalizationIndexB = 1, int sampleIndex = 0, int totalExamples = 5); // Return average error
35 void EvalRegression(const QString &predictedGallery, const QString &truthGallery, QString predictedProperty = "", QString truthProperty = ""); 35 void EvalRegression(const QString &predictedGallery, const QString &truthGallery, QString predictedProperty = "", QString truthProperty = "");
36 void EvalKNN(const QString &knnGraph, const QString &knnTruth, const QString &csv = ""); 36 void EvalKNN(const QString &knnGraph, const QString &knnTruth, const QString &csv = "");
openbr/core/evalutils.cpp
@@ -47,28 +47,34 @@ DetectionKey EvalUtils::getDetectKey(const FileList &amp;files) @@ -47,28 +47,34 @@ DetectionKey EvalUtils::getDetectKey(const FileList &amp;files)
47 // return a list of detections independent of the detection key format 47 // return a list of detections independent of the detection key format
48 QList<Detection> EvalUtils::getDetections(const DetectionKey &key, const File &f, bool isTruth) 48 QList<Detection> EvalUtils::getDetections(const DetectionKey &key, const File &f, bool isTruth)
49 { 49 {
50 - QString pose = f.get<QString>("Pose"); 50 + QString pose = f.get<QString>("Pose", "Frontal");
51 if (pose.contains("Angle")) 51 if (pose.contains("Angle"))
52 pose = "Frontal"; 52 pose = "Frontal";
53 53
  54 + QString label = f.get<QString>("Label", "");
  55 +
54 const QString filePath = f.path() + "/" + f.fileName(); 56 const QString filePath = f.path() + "/" + f.fileName();
55 QList<Detection> dets; 57 QList<Detection> dets;
56 if (key.type == DetectionKey::RectList) { 58 if (key.type == DetectionKey::RectList) {
57 QList<QRectF> rects = f.rects(); 59 QList<QRectF> rects = f.rects();
58 QList<float> confidences = f.getList<float>("Confidences", QList<float>()); 60 QList<float> confidences = f.getList<float>("Confidences", QList<float>());
  61 + QList<QString> labels = f.getList<QString>("Labels", QList<QString>());
59 if (!isTruth && rects.size() != confidences.size()) 62 if (!isTruth && rects.size() != confidences.size())
60 qFatal("You don't have enough confidence. I mean, your detections don't all have confidence measures."); 63 qFatal("You don't have enough confidence. I mean, your detections don't all have confidence measures.");
  64 + if (!labels.empty() && rects.size() != labels.size())
  65 + qFatal("Some of your rects have labels but not all, it's all or nothing I'm afraid");
  66 +
61 for (int i=0; i<rects.size(); i++) { 67 for (int i=0; i<rects.size(); i++) {
62 if (isTruth) 68 if (isTruth)
63 - dets.append(Detection(rects[i], filePath)); 69 + dets.append(Detection(rects[i], filePath, -1, false, "Frontal", labels.empty() ? "" : labels[i]));
64 else 70 else
65 - dets.append(Detection(rects[i], filePath, confidences[i])); 71 + dets.append(Detection(rects[i], filePath, confidences[i], false, "Frontal", labels.empty() ? "" : labels[i]));
66 } 72 }
67 } else if (key.type == DetectionKey::Rect) { 73 } else if (key.type == DetectionKey::Rect) {
68 - dets.append(Detection(f.get<QRectF>(key), filePath, isTruth ? -1 : f.get<float>("Confidence", -1), f.get<bool>("Ignore", false), pose)); 74 + dets.append(Detection(f.get<QRectF>(key), filePath, isTruth ? -1 : f.get<float>("Confidence", -1), f.get<bool>("Ignore", false), pose, label));
69 } else if (key.type == DetectionKey::XYWidthHeight) { 75 } else if (key.type == DetectionKey::XYWidthHeight) {
70 const QRectF rect(f.get<float>(key+"_X"), f.get<float>(key+"_Y"), f.get<float>(key+"_Width"), f.get<float>(key+"_Height")); 76 const QRectF rect(f.get<float>(key+"_X"), f.get<float>(key+"_Y"), f.get<float>(key+"_Width"), f.get<float>(key+"_Height"));
71 - dets.append(Detection(rect, filePath, isTruth ? -1 : f.get<float>("Confidence", -1), f.get<bool>("Ignore", false), pose)); 77 + dets.append(Detection(rect, filePath, isTruth ? -1 : f.get<float>("Confidence", -1), f.get<bool>("Ignore", false), pose, label));
72 } 78 }
73 return dets; 79 return dets;
74 } 80 }
@@ -128,6 +134,27 @@ QMap&lt;QString, Detections&gt; EvalUtils::filterDetections(const QMap&lt;QString, Detect @@ -128,6 +134,27 @@ QMap&lt;QString, Detections&gt; EvalUtils::filterDetections(const QMap&lt;QString, Detect
128 } 134 }
129 if (!filteredDetections.truth.empty()) allFilteredDetections[key] = filteredDetections; 135 if (!filteredDetections.truth.empty()) allFilteredDetections[key] = filteredDetections;
130 } 136 }
  137 +
  138 + return allFilteredDetections;
  139 +}
  140 +
  141 +QMap<QString, Detections> EvalUtils::filterLabels(const QMap<QString, Detections> &allDetections, const QString &label)
  142 +{
  143 + QMap<QString, Detections> allFilteredDetections;
  144 + foreach (QString key, allDetections.keys()) {
  145 + Detections detections = allDetections[key];
  146 + Detections filteredDetections;
  147 + for (int i = 0; i < detections.predicted.size(); i++) {
  148 + if (detections.predicted[i].label == label)
  149 + filteredDetections.predicted.append(detections.predicted[i]);
  150 + }
  151 + for (int i = 0; i < detections.truth.size(); i++) {
  152 + if (detections.truth[i].label == label)
  153 + filteredDetections.truth.append(detections.truth[i]);
  154 + }
  155 + if (!filteredDetections.truth.empty()) allFilteredDetections[key] = filteredDetections;
  156 + }
  157 +
131 return allFilteredDetections; 158 return allFilteredDetections;
132 } 159 }
133 160
@@ -147,6 +174,10 @@ int EvalUtils::associateGroundTruthDetections(QList&lt;ResolvedDetection&gt; &amp;resolved @@ -147,6 +174,10 @@ int EvalUtils::associateGroundTruthDetections(QList&lt;ResolvedDetection&gt; &amp;resolved
147 for (int p = 0; p < detections.predicted.size(); p++) { 174 for (int p = 0; p < detections.predicted.size(); p++) {
148 Detection predicted = detections.predicted[p]; 175 Detection predicted = detections.predicted[p];
149 176
  177 + // Only boxes of the same class can overlap
  178 + if (predicted.label != truth.label)
  179 + continue;
  180 +
150 float predictedWidth = predicted.boundingBox.width(); 181 float predictedWidth = predicted.boundingBox.width();
151 float x, y, width, height; 182 float x, y, width, height;
152 x = predicted.boundingBox.x() + offsets.x()*predictedWidth; 183 x = predicted.boundingBox.x() + offsets.x()*predictedWidth;
@@ -175,7 +206,7 @@ int EvalUtils::associateGroundTruthDetections(QList&lt;ResolvedDetection&gt; &amp;resolved @@ -175,7 +206,7 @@ int EvalUtils::associateGroundTruthDetections(QList&lt;ResolvedDetection&gt; &amp;resolved
175 const Detection predicted = detections.predicted[detection.predicted_idx]; 206 const Detection predicted = detections.predicted[detection.predicted_idx];
176 207
177 if (!truth.ignore) 208 if (!truth.ignore)
178 - resolved.append(ResolvedDetection(predicted.filePath, predicted.boundingBox, predicted.confidence, detection.overlap, truth.boundingBox, truth.pose == predicted.pose)); 209 + resolved.append(ResolvedDetection(predicted.filePath, predicted.boundingBox, predicted.confidence, detection.overlap, truth.boundingBox, truth.pose == predicted.pose, truth.label));
179 210
180 removedTruth.append(detection.truth_idx); 211 removedTruth.append(detection.truth_idx);
181 removedPredicted.append(detection.predicted_idx); 212 removedPredicted.append(detection.predicted_idx);
@@ -192,11 +223,11 @@ int EvalUtils::associateGroundTruthDetections(QList&lt;ResolvedDetection&gt; &amp;resolved @@ -192,11 +223,11 @@ int EvalUtils::associateGroundTruthDetections(QList&lt;ResolvedDetection&gt; &amp;resolved
192 223
193 // False positive 224 // False positive
194 for (int i = 0; i < detections.predicted.size(); i++) 225 for (int i = 0; i < detections.predicted.size(); i++)
195 - if (!removedPredicted.contains(i)) resolved.append(ResolvedDetection(detections.predicted[i].filePath, detections.predicted[i].boundingBox, detections.predicted[i].confidence, 0, QRectF(), false)); 226 + if (!removedPredicted.contains(i)) resolved.append(ResolvedDetection(detections.predicted[i].filePath, detections.predicted[i].boundingBox, detections.predicted[i].confidence, 0, QRectF(), false, detections.predicted[i].label));
196 227
197 // False negative 228 // False negative
198 for (int i = 0; i < detections.truth.size(); i++) 229 for (int i = 0; i < detections.truth.size(); i++)
199 - if (!removedTruth.contains(i) && !detections.truth[i].ignore) falseNegative.append(ResolvedDetection(detections.truth[i].filePath, detections.truth[i].boundingBox, -std::numeric_limits<float>::max(), 0, QRectF(), false)); 230 + if (!removedTruth.contains(i) && !detections.truth[i].ignore) falseNegative.append(ResolvedDetection(detections.truth[i].filePath, detections.truth[i].boundingBox, -std::numeric_limits<float>::max(), 0, QRectF(), false, detections.truth[i].label));
200 } 231 }
201 232
202 if (offsets.x() == 0) { 233 if (offsets.x() == 0) {
openbr/core/evalutils.h
@@ -7,7 +7,8 @@ @@ -7,7 +7,8 @@
7 7
8 namespace EvalUtils 8 namespace EvalUtils
9 { 9 {
10 - struct Detection 10 +
  11 +struct Detection
11 { 12 {
12 QRectF boundingBox; 13 QRectF boundingBox;
13 QString filePath; 14 QString filePath;
@@ -18,14 +19,17 @@ namespace EvalUtils @@ -18,14 +19,17 @@ namespace EvalUtils
18 // true negative, or false negative, it will simply be ignored. 19 // true negative, or false negative, it will simply be ignored.
19 bool ignore; 20 bool ignore;
20 QString pose; 21 QString pose;
  22 + // The label field can be used to distinguish between different object classes
  23 + QString label;
21 24
22 Detection() {} 25 Detection() {}
23 - Detection(const QRectF &boundingBox, const QString &filePath = QString(), float confidence = -1, bool ignore = false, const QString &pose = "Frontal") : 26 + Detection(const QRectF &boundingBox, const QString &filePath = QString(), float confidence = -1, bool ignore = false, const QString &pose = "Frontal", const QString &label = "") :
24 boundingBox(boundingBox), 27 boundingBox(boundingBox),
25 filePath(filePath), 28 filePath(filePath),
26 confidence(confidence), 29 confidence(confidence),
27 ignore(ignore), 30 ignore(ignore),
28 - pose(pose) 31 + pose(pose),
  32 + label(label)
29 {} 33 {}
30 34
31 float overlap(const Detection &other) const 35 float overlap(const Detection &other) const
@@ -50,18 +54,20 @@ struct ResolvedDetection @@ -50,18 +54,20 @@ struct ResolvedDetection
50 QRectF boundingBox, groundTruthBoundingBox; 54 QRectF boundingBox, groundTruthBoundingBox;
51 float confidence, overlap; 55 float confidence, overlap;
52 bool poseMatch; 56 bool poseMatch;
  57 + QString label;
53 ResolvedDetection() : 58 ResolvedDetection() :
54 confidence(-1), 59 confidence(-1),
55 overlap(-1) 60 overlap(-1)
56 {} 61 {}
57 62
58 -ResolvedDetection(const QString &filePath, const QRectF &boundingBox, float confidence, float overlap, const QRectF &groundTruthBoundingBox, bool poseMatch) : 63 +ResolvedDetection(const QString &filePath, const QRectF &boundingBox, float confidence, float overlap, const QRectF &groundTruthBoundingBox, bool poseMatch, const QString &label) :
59 filePath(filePath), 64 filePath(filePath),
60 boundingBox(boundingBox), 65 boundingBox(boundingBox),
61 groundTruthBoundingBox(groundTruthBoundingBox), 66 groundTruthBoundingBox(groundTruthBoundingBox),
62 confidence(confidence), 67 confidence(confidence),
63 overlap(overlap), 68 overlap(overlap),
64 - poseMatch(poseMatch) 69 + poseMatch(poseMatch),
  70 + label(label)
65 {} 71 {}
66 72
67 inline bool operator<(const ResolvedDetection &other) const { return confidence > other.confidence; } 73 inline bool operator<(const ResolvedDetection &other) const { return confidence > other.confidence; }
@@ -99,6 +105,7 @@ struct DetectionOperatingPoint @@ -99,6 +105,7 @@ struct DetectionOperatingPoint
99 QList<Detection> getDetections(const DetectionKey &key, const br::File &f, bool isTruth); 105 QList<Detection> getDetections(const DetectionKey &key, const br::File &f, bool isTruth);
100 QMap<QString, Detections> getDetections(const br::File &predictedGallery, const br::File &truthGallery); 106 QMap<QString, Detections> getDetections(const br::File &predictedGallery, const br::File &truthGallery);
101 QMap<QString, Detections> filterDetections(const QMap<QString, Detections> &allDetections, int threshold, bool useMin = true, float relativeThreshold = 0); 107 QMap<QString, Detections> filterDetections(const QMap<QString, Detections> &allDetections, int threshold, bool useMin = true, float relativeThreshold = 0);
  108 + QMap<QString, Detections> filterLabels(const QMap<QString, Detections> &allDetections, const QString &label);
102 int associateGroundTruthDetections(QList<ResolvedDetection> &resolved, QList<ResolvedDetection> &falseNegative, QMap<QString, Detections> &all, QRectF &offsets); 109 int associateGroundTruthDetections(QList<ResolvedDetection> &resolved, QList<ResolvedDetection> &falseNegative, QMap<QString, Detections> &all, QRectF &offsets);
103 QStringList computeDetectionResults(const QList<ResolvedDetection> &detections, int totalTrueDetections, int numImages, bool discrete, QList<DetectionOperatingPoint> &points); 110 QStringList computeDetectionResults(const QList<ResolvedDetection> &detections, int totalTrueDetections, int numImages, bool discrete, QList<DetectionOperatingPoint> &points);
104 inline int getNumberOfImages(const QMap<QString, Detections> detections) 111 inline int getNumberOfImages(const QMap<QString, Detections> detections)
openbr/openbr.cpp
@@ -126,9 +126,9 @@ void br_eval_clustering(const char *clusters, const char *truth_gallery, const c @@ -126,9 +126,9 @@ void br_eval_clustering(const char *clusters, const char *truth_gallery, const c
126 EvalClustering(clusters, truth_gallery, truth_property, cluster_csv, cluster_property); 126 EvalClustering(clusters, truth_gallery, truth_property, cluster_csv, cluster_property);
127 } 127 }
128 128
129 -float br_eval_detection(const char *predicted_gallery, const char *truth_gallery, const char *csv, bool normalize, int minSize, int maxSize, float relativeMinSize) 129 +float br_eval_detection(const char *predicted_gallery, const char *truth_gallery, const char *csv, bool normalize, int minSize, int maxSize, float relativeMinSize, const char* label)
130 { 130 {
131 - return EvalDetection(predicted_gallery, truth_gallery, csv, normalize, minSize, maxSize, relativeMinSize); 131 + return EvalDetection(predicted_gallery, truth_gallery, csv, normalize, minSize, maxSize, relativeMinSize, label);
132 } 132 }
133 133
134 float br_eval_landmarking(const char *predicted_gallery, const char *truth_gallery, const char *csv, int normalization_index_a, int normalization_index_b, int sample_index, int total_examples) 134 float br_eval_landmarking(const char *predicted_gallery, const char *truth_gallery, const char *csv, int normalization_index_a, int normalization_index_b, int sample_index, int total_examples)
openbr/openbr.h
@@ -58,7 +58,7 @@ BR_EXPORT void br_eval_classification(const char *predicted_gallery, const char @@ -58,7 +58,7 @@ BR_EXPORT void br_eval_classification(const char *predicted_gallery, const char
58 58
59 BR_EXPORT void br_eval_clustering(const char *clusters, const char *truth_gallery, const char *truth_property = "", bool cluster_csv = true, const char *cluster_property = ""); 59 BR_EXPORT void br_eval_clustering(const char *clusters, const char *truth_gallery, const char *truth_property = "", bool cluster_csv = true, const char *cluster_property = "");
60 60
61 -BR_EXPORT float br_eval_detection(const char *predicted_gallery, const char *truth_gallery, const char *csv = "", bool normalize = false, int minSize = 0, int maxSize = 0, float relativeMinSize = 0); 61 +BR_EXPORT float br_eval_detection(const char *predicted_gallery, const char *truth_gallery, const char *csv = "", bool normalize = false, int minSize = 0, int maxSize = 0, float relativeMinSize = 0, const char* label = "");
62 62
63 BR_EXPORT float br_eval_landmarking(const char *predicted_gallery, const char *truth_gallery, const char *csv = "", int normalization_index_a = 0, int normalization_index_b = 1, int sample_index = 0, int total_examples = 5); 63 BR_EXPORT float br_eval_landmarking(const char *predicted_gallery, const char *truth_gallery, const char *csv = "", int normalization_index_a = 0, int normalization_index_b = 1, int sample_index = 0, int total_examples = 5);
64 64