Commit 84b41a656d4380e7bd37e99399ba7c8f11518394
1 parent
2fe3c0ea
added -eval shortcut
Showing
8 changed files
with
55 additions
and
25 deletions
app/br/br.cpp
| @@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
| 20 | #include <stdio.h> | 20 | #include <stdio.h> |
| 21 | #include <stdlib.h> | 21 | #include <stdlib.h> |
| 22 | #include <string.h> | 22 | #include <string.h> |
| 23 | -#include <openbr/openbr.h> | 23 | +#include <openbr/openbr_plugin.h> |
| 24 | 24 | ||
| 25 | /*! | 25 | /*! |
| 26 | * \defgroup cli Command Line Interface | 26 | * \defgroup cli Command Line Interface |
| @@ -95,8 +95,15 @@ public: | @@ -95,8 +95,15 @@ public: | ||
| 95 | check((parc >= 2) && (parc <= 3), "Incorrect parameter count for 'compare'."); | 95 | check((parc >= 2) && (parc <= 3), "Incorrect parameter count for 'compare'."); |
| 96 | br_compare(parv[0], parv[1], parc == 3 ? parv[2] : ""); | 96 | br_compare(parv[0], parv[1], parc == 3 ? parv[2] : ""); |
| 97 | } else if (!strcmp(fun, "eval")) { | 97 | } else if (!strcmp(fun, "eval")) { |
| 98 | - check((parc >= 2) && (parc <= 3), "Incorrect parameter count for 'eval'."); | ||
| 99 | - br_eval(parv[0], parv[1], parc == 3 ? parv[2] : ""); | 98 | + check((parc >= 1) && (parc <= 3), "Incorrect parameter count for 'eval'."); |
| 99 | + if (parc == 1) { | ||
| 100 | + br_eval(parv[0], "", ""); | ||
| 101 | + } else if (parc == 2) { | ||
| 102 | + if (br::File(parv[1]).suffix() == "csv") br_eval(parv[0], "", parv[1]); | ||
| 103 | + else br_eval(parv[0], parv[1], ""); | ||
| 104 | + } else { | ||
| 105 | + br_eval(parv[0], parv[1], parv[2]); | ||
| 106 | + } | ||
| 100 | } else if (!strcmp(fun, "plot")) { | 107 | } else if (!strcmp(fun, "plot")) { |
| 101 | check(parc >= 2, "Incorrect parameter count for 'plot'."); | 108 | check(parc >= 2, "Incorrect parameter count for 'plot'."); |
| 102 | br_plot(parc-1, parv, parv[parc-1], true); | 109 | br_plot(parc-1, parv, parv[parc-1], true); |
| @@ -194,7 +201,7 @@ private: | @@ -194,7 +201,7 @@ private: | ||
| 194 | "-train <gallery> ... <gallery> [{model}]\n" | 201 | "-train <gallery> ... <gallery> [{model}]\n" |
| 195 | "-enroll <input_gallery> ... <input_gallery> {output_gallery}\n" | 202 | "-enroll <input_gallery> ... <input_gallery> {output_gallery}\n" |
| 196 | "-compare <target_gallery> <query_gallery> [{output}]\n" | 203 | "-compare <target_gallery> <query_gallery> [{output}]\n" |
| 197 | - "-eval <simmat> <mask> [{csv}]\n" | 204 | + "-eval <simmat> [<mask>] [{csv}]\n" |
| 198 | "-plot <file> ... <file> {destination}\n" | 205 | "-plot <file> ... <file> {destination}\n" |
| 199 | "\n" | 206 | "\n" |
| 200 | "==== Other Commands ====\n" | 207 | "==== Other Commands ====\n" |
openbr/core/bee.cpp
| @@ -105,7 +105,7 @@ void BEE::writeSigset(const QString &sigset, const br::FileList &files, bool ign | @@ -105,7 +105,7 @@ void BEE::writeSigset(const QString &sigset, const br::FileList &files, bool ign | ||
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | template <typename T> | 107 | template <typename T> |
| 108 | -Mat readMatrix(const br::File &matrix) | 108 | +Mat readMatrix(const br::File &matrix, QString *targetSigset = NULL, QString *querySigset = NULL) |
| 109 | { | 109 | { |
| 110 | // Special case matrix construction | 110 | // Special case matrix construction |
| 111 | if (matrix == "Identity") { | 111 | if (matrix == "Identity") { |
| @@ -150,9 +150,11 @@ Mat readMatrix(const br::File &matrix) | @@ -150,9 +150,11 @@ Mat readMatrix(const br::File &matrix) | ||
| 150 | bool isDistance = (format[0] == 'D'); | 150 | bool isDistance = (format[0] == 'D'); |
| 151 | if (format[1] != '2') qFatal("Invalid matrix header."); | 151 | if (format[1] != '2') qFatal("Invalid matrix header."); |
| 152 | 152 | ||
| 153 | - // Skip sigset lines | ||
| 154 | - file.readLine(); | ||
| 155 | - file.readLine(); | 153 | + // Read sigsets |
| 154 | + if (targetSigset != NULL) *targetSigset = file.readLine().simplified(); | ||
| 155 | + else file.readLine(); | ||
| 156 | + if (querySigset != NULL) *querySigset = file.readLine().simplified(); | ||
| 157 | + else file.readLine(); | ||
| 156 | 158 | ||
| 157 | // Get matrix size | 159 | // Get matrix size |
| 158 | QStringList words = QString(file.readLine()).split(" "); | 160 | QStringList words = QString(file.readLine()).split(" "); |
| @@ -172,9 +174,9 @@ Mat readMatrix(const br::File &matrix) | @@ -172,9 +174,9 @@ Mat readMatrix(const br::File &matrix) | ||
| 172 | return result; | 174 | return result; |
| 173 | } | 175 | } |
| 174 | 176 | ||
| 175 | -Mat BEE::readSimmat(const br::File &simmat) | 177 | +Mat BEE::readSimmat(const br::File &simmat, QString *targetSigset, QString *querySigset) |
| 176 | { | 178 | { |
| 177 | - return readMatrix<Simmat_t>(simmat); | 179 | + return readMatrix<Simmat_t>(simmat, targetSigset, querySigset); |
| 178 | } | 180 | } |
| 179 | 181 | ||
| 180 | Mat BEE::readMask(const br::File &mask) | 182 | Mat BEE::readMask(const br::File &mask) |
| @@ -198,9 +200,9 @@ void writeMatrix(const Mat &m, const QString &matrix, const QString &targetSigse | @@ -198,9 +200,9 @@ void writeMatrix(const Mat &m, const QString &matrix, const QString &targetSigse | ||
| 198 | QtUtils::touchDir(file); | 200 | QtUtils::touchDir(file); |
| 199 | bool success = file.open(QFile::WriteOnly); if (!success) qFatal("Unable to open %s for writing.", qPrintable(matrix)); | 201 | bool success = file.open(QFile::WriteOnly); if (!success) qFatal("Unable to open %s for writing.", qPrintable(matrix)); |
| 200 | file.write("S2\n"); | 202 | file.write("S2\n"); |
| 201 | - file.write(qPrintable(QFileInfo(targetSigset).fileName())); | 203 | + file.write(qPrintable(targetSigset)); |
| 202 | file.write("\n"); | 204 | file.write("\n"); |
| 203 | - file.write(qPrintable(QFileInfo(querySigset).fileName())); | 205 | + file.write(qPrintable(querySigset)); |
| 204 | file.write("\n"); | 206 | file.write("\n"); |
| 205 | file.write("M"); | 207 | file.write("M"); |
| 206 | file.write(qPrintable(matrixType)); | 208 | file.write(qPrintable(matrixType)); |
openbr/core/bee.h
| @@ -39,7 +39,7 @@ namespace BEE | @@ -39,7 +39,7 @@ namespace BEE | ||
| 39 | void writeSigset(const QString &sigset, const br::FileList &files, bool ignoreMetadata = false); | 39 | void writeSigset(const QString &sigset, const br::FileList &files, bool ignoreMetadata = false); |
| 40 | 40 | ||
| 41 | // Matrix IO | 41 | // Matrix IO |
| 42 | - cv::Mat readSimmat(const br::File &simmat); | 42 | + cv::Mat readSimmat(const br::File &simmat, QString *targetSigset = NULL, QString *querySigset = NULL); |
| 43 | cv::Mat readMask(const br::File &mask); | 43 | cv::Mat readMask(const br::File &mask); |
| 44 | void writeSimmat(const cv::Mat &m, const QString &simmat, const QString &targetSigset = "Unknown_Target", const QString &querySigset = "Unknown_Query"); | 44 | void writeSimmat(const cv::Mat &m, const QString &simmat, const QString &targetSigset = "Unknown_Target", const QString &querySigset = "Unknown_Query"); |
| 45 | void writeMask(const cv::Mat &m, const QString &mask, const QString &targetSigset = "Unknown_Target", const QString &querySigset = "Unknown_Query"); | 45 | void writeMask(const cv::Mat &m, const QString &mask, const QString &targetSigset = "Unknown_Target", const QString &querySigset = "Unknown_Query"); |
openbr/core/plot.cpp
| @@ -112,21 +112,37 @@ static float getTAR(const QList<OperatingPoint> &operatingPoints, float FAR) | @@ -112,21 +112,37 @@ static float getTAR(const QList<OperatingPoint> &operatingPoints, float FAR) | ||
| 112 | 112 | ||
| 113 | float Evaluate(const QString &simmat, const QString &mask, const QString &csv) | 113 | float Evaluate(const QString &simmat, const QString &mask, const QString &csv) |
| 114 | { | 114 | { |
| 115 | - qDebug("Evaluating %s with %s", qPrintable(simmat), qPrintable(mask)); | ||
| 116 | - | ||
| 117 | - // Read files | ||
| 118 | - const Mat scores = BEE::readSimmat(simmat); | ||
| 119 | - File maskFile(mask); | ||
| 120 | - maskFile.set("rows", scores.rows); | ||
| 121 | - maskFile.set("columns", scores.cols); | ||
| 122 | - const Mat masks = BEE::readMask(maskFile); | ||
| 123 | - if (scores.size() != masks.size()) qFatal("Simmat (%i,%i) / Mask (%i,%i) size mismatch.", scores.rows, scores.cols, masks.rows, masks.cols); | 115 | + qDebug("Evaluating %s%s%s", |
| 116 | + qPrintable(simmat), | ||
| 117 | + mask.isEmpty() ? "" : qPrintable(" with " + mask), | ||
| 118 | + csv.isEmpty() ? "" : qPrintable(" to " + csv)); | ||
| 119 | + | ||
| 120 | + // Read similarity matrix | ||
| 121 | + QString target, query; | ||
| 122 | + const Mat scores = BEE::readSimmat(simmat, &target, &query); | ||
| 123 | + | ||
| 124 | + // Read mask matrix | ||
| 125 | + Mat truth; | ||
| 126 | + if (mask.isEmpty()) { | ||
| 127 | + // Use the galleries specified in the similarity matrix | ||
| 128 | + truth = BEE::makeMask(TemplateList::fromGallery(target).files(), | ||
| 129 | + TemplateList::fromGallery(query).files()); | ||
| 130 | + } else { | ||
| 131 | + File maskFile(mask); | ||
| 132 | + maskFile.set("rows", scores.rows); | ||
| 133 | + maskFile.set("columns", scores.cols); | ||
| 134 | + truth = BEE::readMask(maskFile); | ||
| 135 | + } | ||
| 124 | 136 | ||
| 125 | - return Evaluate(scores, masks, csv); | 137 | + return Evaluate(scores, truth, csv); |
| 126 | } | 138 | } |
| 127 | 139 | ||
| 128 | float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv) | 140 | float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv) |
| 129 | { | 141 | { |
| 142 | + if (simmat.size() != mask.size()) | ||
| 143 | + qFatal("Similarity matrix (%ix%i) differs in size from mask matrix (%ix%i).", | ||
| 144 | + simmat.rows, simmat.cols, mask.rows, mask.cols); | ||
| 145 | + | ||
| 130 | const int Max_Points = 500; | 146 | const int Max_Points = 500; |
| 131 | float result = -1; | 147 | float result = -1; |
| 132 | 148 |
openbr/core/plot.h
| @@ -26,7 +26,7 @@ namespace br | @@ -26,7 +26,7 @@ namespace br | ||
| 26 | { | 26 | { |
| 27 | 27 | ||
| 28 | void Confusion(const QString &file, float score, int &true_positives, int &false_positives, int &true_negatives, int &false_negatives); | 28 | void Confusion(const QString &file, float score, int &true_positives, int &false_positives, int &true_negatives, int &false_negatives); |
| 29 | -float Evaluate(const QString &simmat, const QString &mask, const QString &csv = ""); // Returns TAR @ FAR = 0.01 | 29 | +float Evaluate(const QString &simmat, const QString &mask = "", const QString &csv = ""); // Returns TAR @ FAR = 0.01 |
| 30 | float Evaluate(const cv::Mat &scores, const cv::Mat &masks, const QString &csv = ""); | 30 | float Evaluate(const cv::Mat &scores, const cv::Mat &masks, const QString &csv = ""); |
| 31 | bool Plot(const QStringList &files, const br::File &destination, bool show = false); | 31 | bool Plot(const QStringList &files, const br::File &destination, bool show = false); |
| 32 | bool PlotMetadata(const QStringList &files, const QString &destination, bool show = false); | 32 | bool PlotMetadata(const QStringList &files, const QString &destination, bool show = false); |
openbr/openbr_plugin.cpp
| @@ -411,6 +411,7 @@ TemplateList TemplateList::fromGallery(const br::File &gallery) | @@ -411,6 +411,7 @@ TemplateList TemplateList::fromGallery(const br::File &gallery) | ||
| 411 | newTemplates[i].file.append(gallery.localMetadata()); | 411 | newTemplates[i].file.append(gallery.localMetadata()); |
| 412 | newTemplates[i].file.append(file.localMetadata()); | 412 | newTemplates[i].file.append(file.localMetadata()); |
| 413 | newTemplates[i].file.set("Index", i+templates.size()); | 413 | newTemplates[i].file.set("Index", i+templates.size()); |
| 414 | + newTemplates[i].file.set("Gallery", gallery.name); | ||
| 414 | if (newTemplates[i].file.getBool("allPartitions")) { | 415 | if (newTemplates[i].file.getBool("allPartitions")) { |
| 415 | if (crossValidate > 0) { | 416 | if (crossValidate > 0) { |
| 416 | // Set template to the first parition | 417 | // Set template to the first parition |
openbr/plugins/output.cpp
| @@ -148,7 +148,10 @@ class mtxOutput : public MatrixOutput | @@ -148,7 +148,10 @@ class mtxOutput : public MatrixOutput | ||
| 148 | ~mtxOutput() | 148 | ~mtxOutput() |
| 149 | { | 149 | { |
| 150 | if (file.isNull() || targetFiles.isEmpty() || queryFiles.isEmpty()) return; | 150 | if (file.isNull() || targetFiles.isEmpty() || queryFiles.isEmpty()) return; |
| 151 | - BEE::writeSimmat(data, file.name); | 151 | + BEE::writeSimmat(data, |
| 152 | + file.name, | ||
| 153 | + targetFiles.first().get<QString>("Gallery", "Unknown_Target"), | ||
| 154 | + queryFiles.first().get<QString>("Gallery", "Unknown_Query")); | ||
| 152 | } | 155 | } |
| 153 | }; | 156 | }; |
| 154 | 157 |
scripts/helloWorld.sh
| @@ -40,3 +40,4 @@ br -algorithm Eigenfaces -path MEDS/img -compare MEDS/sigset/MEDS_frontal_target | @@ -40,3 +40,4 @@ br -algorithm Eigenfaces -path MEDS/img -compare MEDS/sigset/MEDS_frontal_target | ||
| 40 | # br -algorithm Eigenfaces -path MEDS/img -enroll MEDS/sigset/MEDS_frontal_target.xml target.gal -enroll MEDS/sigset/MEDS_frontal_query.xml query.gal -compare target.gal query.gal scores.mtx | 40 | # br -algorithm Eigenfaces -path MEDS/img -enroll MEDS/sigset/MEDS_frontal_target.xml target.gal -enroll MEDS/sigset/MEDS_frontal_query.xml query.gal -compare target.gal query.gal scores.mtx |
| 41 | 41 | ||
| 42 | # Evaluate Eigenfaces accuracy | 42 | # Evaluate Eigenfaces accuracy |
| 43 | +br -eval scores.mtx results.csv -plot results.csv results.pdf |