Commit 3d4c5b16c11a57f1859e7b691e84e6262dd5ca41
Merge branch 'master' of https://github.com/biometrics/openbr
Showing
6 changed files
with
128 additions
and
37 deletions
openbr/core/bee.cpp
| ... | ... | @@ -239,9 +239,11 @@ void BEE::makeMask(const QString &targetInput, const QString &queryInput, const |
| 239 | 239 | FileList queries = (queryInput == ".") ? targets : TemplateList::fromGallery(queryInput).files(); |
| 240 | 240 | int partitions = targets.first().get<int>("crossValidate"); |
| 241 | 241 | if (partitions == 0) writeMask(makeMask(targets, queries), mask, targetInput, queryInput); |
| 242 | - else for (int i=0; i<partitions; i++) { | |
| 243 | - QString maskPartition = mask; | |
| 244 | - writeMask(makeMask(targets, queries, i), maskPartition.insert(maskPartition.indexOf('.'),"Partition_" + QString::number(i)), targetInput, queryInput); | |
| 242 | + else { | |
| 243 | + if (!mask.contains("%1")) qFatal("Mask file name missing partition number place marker (%1)"); | |
| 244 | + for (int i=0; i<partitions; i++) { | |
| 245 | + writeMask(makeMask(targets, queries, i), mask.arg(i), targetInput, queryInput); | |
| 246 | + } | |
| 245 | 247 | } |
| 246 | 248 | } |
| 247 | 249 | ... | ... |
openbr/core/core.cpp
| ... | ... | @@ -202,10 +202,20 @@ struct AlgorithmCore |
| 202 | 202 | retrieveOrEnroll(targetGallery, t, targetFiles); |
| 203 | 203 | retrieveOrEnroll(queryGallery, q, queryFiles); |
| 204 | 204 | |
| 205 | - // Make multiple outputs if output[split] | |
| 205 | + QList<int> partitionSizes; | |
| 206 | + QList<File> outputFiles; | |
| 207 | + if (output.contains("split")) { | |
| 208 | + if (!output.fileName().contains("%1")) qFatal("Output file name missing split number place marker (%1)"); | |
| 209 | + partitionSizes = output.getList<int>("split"); | |
| 210 | + for (int i=0; i<partitionSizes.size(); i++) { | |
| 211 | + File splitOutputFile = output.fileName().arg(i); | |
| 212 | + outputFiles.append(splitOutputFile); | |
| 213 | + } | |
| 214 | + } | |
| 215 | + else outputFiles.append(output); | |
| 206 | 216 | |
| 207 | - // Split each | |
| 208 | - QScopedPointer<Output> o(Output::make(output, targetFiles, queryFiles)); | |
| 217 | + QList<Output*> outputs; | |
| 218 | + foreach (const File &outputFile, outputFiles) outputs.append(Output::make(outputFile, targetFiles, queryFiles)); | |
| 209 | 219 | |
| 210 | 220 | if (distance.isNull()) qFatal("Null distance."); |
| 211 | 221 | Globals->currentStep = 0; |
| ... | ... | @@ -218,26 +228,35 @@ struct AlgorithmCore |
| 218 | 228 | queryBlock++; |
| 219 | 229 | TemplateList queries = q->readBlock(&queryDone); |
| 220 | 230 | |
| 221 | - // Split queries by matrix into list of template lists if output[split] | |
| 222 | - // foreach TemplateList in perMatrixQueries | |
| 231 | + QList<TemplateList> queryPartitions; | |
| 232 | + if (!partitionSizes.empty()) queryPartitions = queries.partition(partitionSizes); | |
| 233 | + else queryPartitions.append(queries); | |
| 223 | 234 | |
| 224 | - int targetBlock = -1; | |
| 225 | - bool targetDone = false; | |
| 226 | - while (!targetDone) { | |
| 227 | - targetBlock++; | |
| 228 | - // Check if templates contain the same number of matrices | |
| 229 | - // Split targets by matrix into templateList if output[split] for matrices i | |
| 235 | + for (int i=0; i<queryPartitions.size(); i++) { | |
| 236 | + int targetBlock = -1; | |
| 237 | + bool targetDone = false; | |
| 238 | + while (!targetDone) { | |
| 239 | + targetBlock++; | |
| 230 | 240 | |
| 231 | - TemplateList targets = t->readBlock(&targetDone); | |
| 241 | + TemplateList targets = t->readBlock(&targetDone); | |
| 232 | 242 | |
| 233 | - o->setBlock(queryBlock, targetBlock); | |
| 234 | - distance->compare(targets, queries, o.data()); | |
| 243 | + QList<TemplateList> targetPartitions; | |
| 244 | + if (!partitionSizes.empty()) targetPartitions = targets.partition(partitionSizes); | |
| 245 | + else targetPartitions.append(targets); | |
| 235 | 246 | |
| 236 | - Globals->currentStep += double(targets.size()) * double(queries.size()); | |
| 237 | - Globals->printStatus(); | |
| 247 | + if (queryPartitions[i].first().size() != targetPartitions[i].first().size()) qFatal("Query and target templates have different number of matrices."); | |
| 248 | + | |
| 249 | + outputs[i]->setBlock(queryBlock, targetBlock); | |
| 250 | + distance->compare(targetPartitions[i], queryPartitions[i], outputs[i]); | |
| 251 | + | |
| 252 | + Globals->currentStep += double(targets.size()) * double(queries.size()); | |
| 253 | + Globals->printStatus(); | |
| 254 | + } | |
| 238 | 255 | } |
| 239 | 256 | } |
| 240 | 257 | |
| 258 | + qDeleteAll(outputs); | |
| 259 | + | |
| 241 | 260 | const float speed = 1000 * Globals->totalSteps / Globals->startTime.elapsed() / std::max(1, abs(Globals->parallelism)); |
| 242 | 261 | if (!Globals->quiet && (Globals->totalSteps > 1)) fprintf(stderr, "\rSPEED=%.1e \n", speed); |
| 243 | 262 | Globals->totalSteps = 0; | ... | ... |
openbr/core/qtutils.cpp
| ... | ... | @@ -285,6 +285,28 @@ void QtUtils::checkArgsSize(const QString &name, const QStringList &args, int mi |
| 285 | 285 | if (args.size() > max) qFatal("%s expects no more than %d arguments, got %d", qPrintable(name), max, args.size()); |
| 286 | 286 | } |
| 287 | 287 | |
| 288 | +QPointF QtUtils::toPoint(const QString &string) | |
| 289 | +{ | |
| 290 | + QStringList values = string.split(','); | |
| 291 | + if (values.size() == 2) { | |
| 292 | + values[1].chop(1); | |
| 293 | + QPointF point(values[0].mid(1).toFloat(), values[1].toFloat()); | |
| 294 | + return point; | |
| 295 | + } | |
| 296 | + else qFatal("Failed to convert %s to QPoint format.", qPrintable(string)); | |
| 297 | +} | |
| 298 | + | |
| 299 | +QRectF QtUtils::toRect(const QString &string) | |
| 300 | +{ | |
| 301 | + QStringList values = string.split(','); | |
| 302 | + if (values.size() == 4) { | |
| 303 | + values[3].chop(1); | |
| 304 | + QRectF rect(values[0].mid(1).toFloat(), values[1].toFloat(), values[2].toFloat(), values[3].toFloat()); | |
| 305 | + return rect; | |
| 306 | + } | |
| 307 | + else qFatal("Failed to convert %s to QRect format.", qPrintable(string)); | |
| 308 | +} | |
| 309 | + | |
| 288 | 310 | bool QtUtils::runRScript(const QString &file) |
| 289 | 311 | { |
| 290 | 312 | QProcess RScript; | ... | ... |
openbr/core/qtutils.h
| ... | ... | @@ -62,6 +62,8 @@ namespace QtUtils |
| 62 | 62 | QString shortTextHash(QString string); |
| 63 | 63 | QStringList parse(QString args, char split = ','); |
| 64 | 64 | void checkArgsSize(const QString &name, const QStringList &args, int min, int max); |
| 65 | + QPointF toPoint(const QString &string); | |
| 66 | + QRectF toRect(const QString &string); | |
| 65 | 67 | |
| 66 | 68 | /**** Process Utilities ****/ |
| 67 | 69 | bool runRScript(const QString &file); | ... | ... |
openbr/openbr_plugin.cpp
| ... | ... | @@ -55,11 +55,11 @@ QString File::flat() const |
| 55 | 55 | if (value.isNull()) values.append(key); |
| 56 | 56 | else { |
| 57 | 57 | if (QString(value.typeName()) == "QVariantList") { |
| 58 | - QStringList landmarks; | |
| 59 | - foreach(const QVariant &landmark, qvariant_cast<QVariantList>(value)) { | |
| 60 | - landmarks.append(QtUtils::toString(landmark)); | |
| 58 | + QStringList variants; | |
| 59 | + foreach(const QVariant &variant, qvariant_cast<QVariantList>(value)) { | |
| 60 | + variants.append(QtUtils::toString(variant)); | |
| 61 | 61 | } |
| 62 | - if (!landmarks.isEmpty()) values.append(key + "=[" + landmarks.join(", ") + "]"); | |
| 62 | + if (!variants.isEmpty()) values.append(key + "=[" + variants.join(", ") + "]"); | |
| 63 | 63 | } |
| 64 | 64 | else values.append(key + "=" + QtUtils::toString(value)); |
| 65 | 65 | } |
| ... | ... | @@ -147,26 +147,26 @@ void File::set(const QString &key, const QVariant &value) |
| 147 | 147 | m_metadata.insert(key, value); |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | +// Note that we assume all values within a parameter list are the same type | |
| 150 | 151 | void File::set(const QString &key, const QString &value) |
| 151 | 152 | { |
| 152 | 153 | if (value[0] == '[') /* QVariantList */ { |
| 153 | 154 | QStringList values = value.mid(1, value.size()-2).split(", "); |
| 154 | - foreach(const QString &word, values) set(key, word); | |
| 155 | - } | |
| 156 | - else if (value[0] == '(') { | |
| 157 | - QStringList values = value.split(','); | |
| 158 | - if (values.size() == 2) /* QPointF */ { | |
| 159 | - values[1].chop(1); | |
| 160 | - QPointF point(values[0].mid(1).toFloat(), values[1].toFloat()); | |
| 161 | - if (key != "Points") m_metadata.insert(key, point); | |
| 162 | - else appendPoint(point); | |
| 155 | + QList<QVariant> variants; | |
| 156 | + if (values[0][0] == '(') /* List of Points or Rects */ { | |
| 157 | + if (values[0].split(',').size() == 2) /* List of Points */ foreach(const QString &word, values) variants.append(QtUtils::toPoint(word)); | |
| 158 | + else if (values[0].split(',').size() == 4) /* List of Rects */ foreach(const QString &word, values) variants.append(QtUtils::toRect(word)); | |
| 159 | + else qFatal("Incorrect landmark format."); | |
| 163 | 160 | } |
| 164 | - else /* QRectF */ { | |
| 165 | - values[3].chop(1); | |
| 166 | - QRectF rect(values[0].mid(1).toFloat(), values[1].toFloat(), values[2].toFloat(), values[3].toFloat()); | |
| 167 | - if (key != "Rects") m_metadata.insert(key, rect); | |
| 168 | - else appendRect(rect); | |
| 161 | + else { | |
| 162 | + foreach(const QString &word, values) variants.append(word.toFloat()); | |
| 169 | 163 | } |
| 164 | + m_metadata.insert(key, variants); | |
| 165 | + } | |
| 166 | + else if (value[0] == '(') /* Point or Rect */ { | |
| 167 | + if (value.split(',').size() == 2) /* QPointF */ m_metadata.insert(key, QtUtils::toPoint(value)); | |
| 168 | + else if (value.split(',').size() == 4) /* QRectF */ m_metadata.insert(key, QtUtils::toRect(value)); | |
| 169 | + else qFatal("Incorrect landmark format."); | |
| 170 | 170 | } |
| 171 | 171 | else m_metadata.insert(key, value); |
| 172 | 172 | } | ... | ... |
openbr/openbr_plugin.h
| ... | ... | @@ -207,6 +207,19 @@ struct BR_EXPORT File |
| 207 | 207 | return variant.value<T>(); |
| 208 | 208 | } |
| 209 | 209 | |
| 210 | + /*!< \brief Returns a list of type T for the key, throwing an error if the key does not exist or if the value cannot be converted to the specified type. */ | |
| 211 | + template <typename T> | |
| 212 | + QList<T> getList(const QString &key) const | |
| 213 | + { | |
| 214 | + if (!contains(key)) qFatal("Missing key: %s", qPrintable(key)); | |
| 215 | + QList<T> list; | |
| 216 | + foreach (const QVariant &item, m_metadata[key].toList()) { | |
| 217 | + if (item.canConvert<T>()) list.append(item.value<T>()); | |
| 218 | + else qFatal("Failed to convert value for key %s.", qPrintable(key)); | |
| 219 | + } | |
| 220 | + return list; | |
| 221 | + } | |
| 222 | + | |
| 210 | 223 | /*!< \brief Specialization for boolean type. */ |
| 211 | 224 | bool getBool(const QString &key) const; |
| 212 | 225 | |
| ... | ... | @@ -375,6 +388,39 @@ struct TemplateList : public QList<Template> |
| 375 | 388 | } |
| 376 | 389 | |
| 377 | 390 | /*! |
| 391 | + * \brief Returns a #br::TemplateList containing templates with one matrix at the specified index \em index. | |
| 392 | + */ | |
| 393 | + QList<TemplateList> partition(const QList<int> &partitionSizes) const | |
| 394 | + { | |
| 395 | + int sum = 0; | |
| 396 | + QList<TemplateList> partitions; partitions.reserve(partitionSizes.size()); | |
| 397 | + | |
| 398 | + for(int i=0; i<partitionSizes.size(); i++) { | |
| 399 | + partitions.append(TemplateList()); | |
| 400 | + sum+=partitionSizes[i]; | |
| 401 | + } | |
| 402 | + | |
| 403 | + if (sum != first().size()) qFatal("Partition sizes do not span template matrices properly"); | |
| 404 | + | |
| 405 | + foreach (const Template &t, *this) { | |
| 406 | + int index = 0; | |
| 407 | + while (index < t.size()) { | |
| 408 | + for (int i=0; i<partitionSizes.size(); i++) { | |
| 409 | + Template newTemplate; | |
| 410 | + for (int j=0; j<partitionSizes[i]; j++) { | |
| 411 | + newTemplate.append(t[index]); | |
| 412 | + index++; | |
| 413 | + } | |
| 414 | + // Append to the ith element of partitions | |
| 415 | + partitions[i].append(newTemplate); | |
| 416 | + } | |
| 417 | + } | |
| 418 | + } | |
| 419 | + | |
| 420 | + return partitions; | |
| 421 | + } | |
| 422 | + | |
| 423 | + /*! | |
| 378 | 424 | * \brief Returns #br::Template::file for each template in the list. |
| 379 | 425 | */ |
| 380 | 426 | FileList files() const | ... | ... |