diff --git a/openbr/core/core.cpp b/openbr/core/core.cpp index fae1184..cea16f1 100644 --- a/openbr/core/core.cpp +++ b/openbr/core/core.cpp @@ -453,14 +453,23 @@ void br::Convert(const File &fileType, const File &inputFile, const File &output const FileList targetFiles = TemplateList::fromGallery(target).files(); const FileList queryFiles = TemplateList::fromGallery(query).files(); - if (targetFiles.size() != m.cols || queryFiles.size() != m.rows) + if ((targetFiles.size() != m.cols || queryFiles.size() != m.rows) + && (m.cols != 1 || targetFiles.size() != m.rows || queryFiles.size() != m.rows)) qFatal("Similarity matrix and file size mismatch."); QSharedPointer o(Factory::make(outputFile)); o->initialize(targetFiles, queryFiles); - for (int i=0; i(o.data()); + if (mOut) + mOut->data.create(queryFiles.size(), 1, CV_32FC1); + } + + o->setBlock(0,0); + for (int i=0; i < m.rows; i++) + for (int j=0; j < m.cols; j++) o->setRelative(m.at(i,j), i, j); } else { qFatal("Unrecognized file type %s.", qPrintable(fileType.flat())); diff --git a/openbr/core/eval.cpp b/openbr/core/eval.cpp index 2406a01..15246cc 100644 --- a/openbr/core/eval.cpp +++ b/openbr/core/eval.cpp @@ -65,9 +65,26 @@ static float getTAR(const QList &operatingPoints, float FAR) return m * FAR + b; } +// Decide whether to construct a normal mask matrix, or a pairwise mask by comparing the dimensions of +// scores with the size of the target and query lists +static cv::Mat constructMatchingMask(const cv::Mat & scores, const FileList & target, const FileList & query, int partition=0) +{ + // If the dimensions of the score matrix match the sizes of the target and query lists, construct a normal mask matrix + if (target.size() == scores.cols && query.size() == scores.rows) + return BEE::makeMask(target, query, partition); + // If this looks like a pairwise comparison (1 column score matrix, equal length target and query sets), construct a + // mask for that + else if (scores.cols == 1 && target.size() == query.size()) { + return BEE::makePairwiseMask(target, query, partition); + } + // otherwise, we fail + else + qFatal("Unable to construct mask for %d by %d score matrix from %d element query set, and %d element target set ", scores.rows, scores.cols, query.length(), target.length()); +} + float Evaluate(const cv::Mat &scores, const FileList &target, const FileList &query, const QString &csv, int partition) { - return Evaluate(scores, BEE::makeMask(target, query, partition), csv); + return Evaluate(scores, constructMatchingMask(scores, target, query, partition), csv); } float Evaluate(const QString &simmat, const QString &mask, const QString &csv) @@ -93,8 +110,9 @@ float Evaluate(const QString &simmat, const QString &mask, const QString &csv) // Use the galleries specified in the similarity matrix if (target.isEmpty()) qFatal("Unspecified target gallery."); if (query.isEmpty()) qFatal("Unspecified query gallery."); - truth = BEE::makeMask(TemplateList::fromGallery(target).files(), - TemplateList::fromGallery(query).files()); + + truth = constructMatchingMask(scores, TemplateList::fromGallery(target).files(), + TemplateList::fromGallery(query).files()); } else { File maskFile(mask); maskFile.set("rows", scores.rows); diff --git a/openbr/plugins/output.cpp b/openbr/plugins/output.cpp index 9f8301b..1ad0995 100644 --- a/openbr/plugins/output.cpp +++ b/openbr/plugins/output.cpp @@ -371,7 +371,7 @@ class evalOutput : public MatrixOutput if (data.data) { const QString csv = QString(file.name).replace(".eval", ".csv"); if ((Globals->crossValidate == 0) || (!crossValidate)) { - Evaluate(data, BEE::makeMask(targetFiles, queryFiles), csv); + Evaluate(data,targetFiles, queryFiles, csv); } else { QFutureSynchronizer futures; for (int i=0; icrossValidate; i++)