Commit 3d4c5b16c11a57f1859e7b691e84e6262dd5ca41

Authored by Josh Klontz
2 parents bbf17e0d ad5a289a

Merge branch 'master' of https://github.com/biometrics/openbr

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 &amp;name, const QStringList &amp;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 &amp;key, const QVariant &amp;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&lt;Template&gt;
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
... ...