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,9 +239,11 @@ void BEE::makeMask(const QString &targetInput, const QString &queryInput, const
239 FileList queries = (queryInput == ".") ? targets : TemplateList::fromGallery(queryInput).files(); 239 FileList queries = (queryInput == ".") ? targets : TemplateList::fromGallery(queryInput).files();
240 int partitions = targets.first().get<int>("crossValidate"); 240 int partitions = targets.first().get<int>("crossValidate");
241 if (partitions == 0) writeMask(makeMask(targets, queries), mask, targetInput, queryInput); 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,10 +202,20 @@ struct AlgorithmCore
202 retrieveOrEnroll(targetGallery, t, targetFiles); 202 retrieveOrEnroll(targetGallery, t, targetFiles);
203 retrieveOrEnroll(queryGallery, q, queryFiles); 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 if (distance.isNull()) qFatal("Null distance."); 220 if (distance.isNull()) qFatal("Null distance.");
211 Globals->currentStep = 0; 221 Globals->currentStep = 0;
@@ -218,26 +228,35 @@ struct AlgorithmCore @@ -218,26 +228,35 @@ struct AlgorithmCore
218 queryBlock++; 228 queryBlock++;
219 TemplateList queries = q->readBlock(&queryDone); 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 const float speed = 1000 * Globals->totalSteps / Globals->startTime.elapsed() / std::max(1, abs(Globals->parallelism)); 260 const float speed = 1000 * Globals->totalSteps / Globals->startTime.elapsed() / std::max(1, abs(Globals->parallelism));
242 if (!Globals->quiet && (Globals->totalSteps > 1)) fprintf(stderr, "\rSPEED=%.1e \n", speed); 261 if (!Globals->quiet && (Globals->totalSteps > 1)) fprintf(stderr, "\rSPEED=%.1e \n", speed);
243 Globals->totalSteps = 0; 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,6 +285,28 @@ void QtUtils::checkArgsSize(const QString &amp;name, const QStringList &amp;args, int mi
285 if (args.size() > max) qFatal("%s expects no more than %d arguments, got %d", qPrintable(name), max, args.size()); 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 bool QtUtils::runRScript(const QString &file) 310 bool QtUtils::runRScript(const QString &file)
289 { 311 {
290 QProcess RScript; 312 QProcess RScript;
openbr/core/qtutils.h
@@ -62,6 +62,8 @@ namespace QtUtils @@ -62,6 +62,8 @@ namespace QtUtils
62 QString shortTextHash(QString string); 62 QString shortTextHash(QString string);
63 QStringList parse(QString args, char split = ','); 63 QStringList parse(QString args, char split = ',');
64 void checkArgsSize(const QString &name, const QStringList &args, int min, int max); 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 /**** Process Utilities ****/ 68 /**** Process Utilities ****/
67 bool runRScript(const QString &file); 69 bool runRScript(const QString &file);
openbr/openbr_plugin.cpp
@@ -55,11 +55,11 @@ QString File::flat() const @@ -55,11 +55,11 @@ QString File::flat() const
55 if (value.isNull()) values.append(key); 55 if (value.isNull()) values.append(key);
56 else { 56 else {
57 if (QString(value.typeName()) == "QVariantList") { 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 else values.append(key + "=" + QtUtils::toString(value)); 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,26 +147,26 @@ void File::set(const QString &amp;key, const QVariant &amp;value)
147 m_metadata.insert(key, value); 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 void File::set(const QString &key, const QString &value) 151 void File::set(const QString &key, const QString &value)
151 { 152 {
152 if (value[0] == '[') /* QVariantList */ { 153 if (value[0] == '[') /* QVariantList */ {
153 QStringList values = value.mid(1, value.size()-2).split(", "); 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 else m_metadata.insert(key, value); 171 else m_metadata.insert(key, value);
172 } 172 }
openbr/openbr_plugin.h
@@ -207,6 +207,19 @@ struct BR_EXPORT File @@ -207,6 +207,19 @@ struct BR_EXPORT File
207 return variant.value<T>(); 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 /*!< \brief Specialization for boolean type. */ 223 /*!< \brief Specialization for boolean type. */
211 bool getBool(const QString &key) const; 224 bool getBool(const QString &key) const;
212 225
@@ -375,6 +388,39 @@ struct TemplateList : public QList&lt;Template&gt; @@ -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 * \brief Returns #br::Template::file for each template in the list. 424 * \brief Returns #br::Template::file for each template in the list.
379 */ 425 */
380 FileList files() const 426 FileList files() const