diff --git a/openbr/core/bee.cpp b/openbr/core/bee.cpp index 93d61d6..cf04b47 100644 --- a/openbr/core/bee.cpp +++ b/openbr/core/bee.cpp @@ -239,9 +239,11 @@ void BEE::makeMask(const QString &targetInput, const QString &queryInput, const FileList queries = (queryInput == ".") ? targets : TemplateList::fromGallery(queryInput).files(); int partitions = targets.first().get("crossValidate"); if (partitions == 0) writeMask(makeMask(targets, queries), mask, targetInput, queryInput); - else for (int i=0; i partitionSizes; + QList outputFiles; + if (output.contains("split")) { + if (!output.fileName().contains("%1")) qFatal("Output file name missing split number place marker (%1)"); + partitionSizes = output.getList("split"); + for (int i=0; i o(Output::make(output, targetFiles, queryFiles)); + QList outputs; + foreach (const File &outputFile, outputFiles) outputs.append(Output::make(outputFile, targetFiles, queryFiles)); if (distance.isNull()) qFatal("Null distance."); Globals->currentStep = 0; @@ -218,26 +228,35 @@ struct AlgorithmCore queryBlock++; TemplateList queries = q->readBlock(&queryDone); - // Split queries by matrix into list of template lists if output[split] - // foreach TemplateList in perMatrixQueries + QList queryPartitions; + if (!partitionSizes.empty()) queryPartitions = queries.partition(partitionSizes); + else queryPartitions.append(queries); - int targetBlock = -1; - bool targetDone = false; - while (!targetDone) { - targetBlock++; - // Check if templates contain the same number of matrices - // Split targets by matrix into templateList if output[split] for matrices i + for (int i=0; ireadBlock(&targetDone); + TemplateList targets = t->readBlock(&targetDone); - o->setBlock(queryBlock, targetBlock); - distance->compare(targets, queries, o.data()); + QList targetPartitions; + if (!partitionSizes.empty()) targetPartitions = targets.partition(partitionSizes); + else targetPartitions.append(targets); - Globals->currentStep += double(targets.size()) * double(queries.size()); - Globals->printStatus(); + if (queryPartitions[i].first().size() != targetPartitions[i].first().size()) qFatal("Query and target templates have different number of matrices."); + + outputs[i]->setBlock(queryBlock, targetBlock); + distance->compare(targetPartitions[i], queryPartitions[i], outputs[i]); + + Globals->currentStep += double(targets.size()) * double(queries.size()); + Globals->printStatus(); + } } } + qDeleteAll(outputs); + const float speed = 1000 * Globals->totalSteps / Globals->startTime.elapsed() / std::max(1, abs(Globals->parallelism)); if (!Globals->quiet && (Globals->totalSteps > 1)) fprintf(stderr, "\rSPEED=%.1e \n", speed); Globals->totalSteps = 0; diff --git a/openbr/core/qtutils.cpp b/openbr/core/qtutils.cpp index e440638..a5590d5 100644 --- a/openbr/core/qtutils.cpp +++ b/openbr/core/qtutils.cpp @@ -285,6 +285,28 @@ void QtUtils::checkArgsSize(const QString &name, const QStringList &args, int mi if (args.size() > max) qFatal("%s expects no more than %d arguments, got %d", qPrintable(name), max, args.size()); } +QPointF QtUtils::toPoint(const QString &string) +{ + QStringList values = string.split(','); + if (values.size() == 2) { + values[1].chop(1); + QPointF point(values[0].mid(1).toFloat(), values[1].toFloat()); + return point; + } + else qFatal("Failed to convert %s to QPoint format.", qPrintable(string)); +} + +QRectF QtUtils::toRect(const QString &string) +{ + QStringList values = string.split(','); + if (values.size() == 4) { + values[3].chop(1); + QRectF rect(values[0].mid(1).toFloat(), values[1].toFloat(), values[2].toFloat(), values[3].toFloat()); + return rect; + } + else qFatal("Failed to convert %s to QRect format.", qPrintable(string)); +} + bool QtUtils::runRScript(const QString &file) { QProcess RScript; diff --git a/openbr/core/qtutils.h b/openbr/core/qtutils.h index ebe7d8c..f6f6062 100644 --- a/openbr/core/qtutils.h +++ b/openbr/core/qtutils.h @@ -62,6 +62,8 @@ namespace QtUtils QString shortTextHash(QString string); QStringList parse(QString args, char split = ','); void checkArgsSize(const QString &name, const QStringList &args, int min, int max); + QPointF toPoint(const QString &string); + QRectF toRect(const QString &string); /**** Process Utilities ****/ bool runRScript(const QString &file); diff --git a/openbr/openbr_plugin.cpp b/openbr/openbr_plugin.cpp index 71dc0e7..5404e11 100644 --- a/openbr/openbr_plugin.cpp +++ b/openbr/openbr_plugin.cpp @@ -55,11 +55,11 @@ QString File::flat() const if (value.isNull()) values.append(key); else { if (QString(value.typeName()) == "QVariantList") { - QStringList landmarks; - foreach(const QVariant &landmark, qvariant_cast(value)) { - landmarks.append(QtUtils::toString(landmark)); + QStringList variants; + foreach(const QVariant &variant, qvariant_cast(value)) { + variants.append(QtUtils::toString(variant)); } - if (!landmarks.isEmpty()) values.append(key + "=[" + landmarks.join(", ") + "]"); + if (!variants.isEmpty()) values.append(key + "=[" + variants.join(", ") + "]"); } else values.append(key + "=" + QtUtils::toString(value)); } @@ -147,26 +147,26 @@ void File::set(const QString &key, const QVariant &value) m_metadata.insert(key, value); } +// Note that we assume all values within a parameter list are the same type void File::set(const QString &key, const QString &value) { if (value[0] == '[') /* QVariantList */ { QStringList values = value.mid(1, value.size()-2).split(", "); - foreach(const QString &word, values) set(key, word); - } - else if (value[0] == '(') { - QStringList values = value.split(','); - if (values.size() == 2) /* QPointF */ { - values[1].chop(1); - QPointF point(values[0].mid(1).toFloat(), values[1].toFloat()); - if (key != "Points") m_metadata.insert(key, point); - else appendPoint(point); + QList variants; + if (values[0][0] == '(') /* List of Points or Rects */ { + if (values[0].split(',').size() == 2) /* List of Points */ foreach(const QString &word, values) variants.append(QtUtils::toPoint(word)); + else if (values[0].split(',').size() == 4) /* List of Rects */ foreach(const QString &word, values) variants.append(QtUtils::toRect(word)); + else qFatal("Incorrect landmark format."); } - else /* QRectF */ { - values[3].chop(1); - QRectF rect(values[0].mid(1).toFloat(), values[1].toFloat(), values[2].toFloat(), values[3].toFloat()); - if (key != "Rects") m_metadata.insert(key, rect); - else appendRect(rect); + else { + foreach(const QString &word, values) variants.append(word.toFloat()); } + m_metadata.insert(key, variants); + } + else if (value[0] == '(') /* Point or Rect */ { + if (value.split(',').size() == 2) /* QPointF */ m_metadata.insert(key, QtUtils::toPoint(value)); + else if (value.split(',').size() == 4) /* QRectF */ m_metadata.insert(key, QtUtils::toRect(value)); + else qFatal("Incorrect landmark format."); } else m_metadata.insert(key, value); } diff --git a/openbr/openbr_plugin.h b/openbr/openbr_plugin.h index 69c97ec..71787da 100644 --- a/openbr/openbr_plugin.h +++ b/openbr/openbr_plugin.h @@ -207,6 +207,19 @@ struct BR_EXPORT File return variant.value(); } + /*!< \brief TODO. */ + template + QList getList(const QString &key) const + { + if (!contains(key)) qFatal("Missing key: %s", qPrintable(key)); + QList list; + foreach (const QVariant &item, m_metadata[key].toList()) { + if (item.canConvert()) list.append(item.value()); + else qFatal("Failed to convert value for key %s.", qPrintable(key)); + } + return list; + } + /*!< \brief Specialization for boolean type. */ bool getBool(const QString &key) const; @@ -374,6 +387,39 @@ struct TemplateList : public QList