Commit 7d2c5ba7c4ad289c4f86e34b65f36463d37d80d5

Authored by Josh Klontz
2 parents 8a5eb541 6e96c4e0

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

data/README.md
... ... @@ -7,9 +7,9 @@
7 7 * [FRGC](FRGC/README.md)
8 8 * [LFW](LFW/LFW.md)
9 9 * [MEDS](MEDS/README.md)
  10 +* [MNIST](MNIST/README.md)
10 11 * [PCSO](PCSO/README.md)
11 12  
12   -For both practical and legal reasons we don't include images in this repository.
13   -Open source datasets can be downloaded using `../scripts/downloadDatasets.sh`.
  13 +For both practical and legal reasons we only include images for some of the datasets in this repository.
14 14 Researchers should contact the respective owners of the other datasets in order to obtain a copy.
15 15 The provided sigsets indicate how the images are expected to be arranged in directories, generally following the conventions established by the original authors.
... ...
openbr/core/core.cpp
... ... @@ -248,9 +248,8 @@ struct AlgorithmCore
248 248 if (!partitionSizes.empty()) targetPartitions = targets.partition(partitionSizes);
249 249 else targetPartitions.append(targets);
250 250  
251   - if (queryPartitions[i].first().size() != targetPartitions[i].first().size()) qFatal("Query and target templates have different number of matrices.");
252   -
253 251 outputs[i]->setBlock(queryBlock, targetBlock);
  252 +
254 253 distance->compare(targetPartitions[i], queryPartitions[i], outputs[i]);
255 254  
256 255 Globals->currentStep += double(targets.size()) * double(queries.size());
... ...
openbr/core/plot.cpp
... ... @@ -248,24 +248,29 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv)
248 248 lines.append(qPrintable(QString("BC,0.001,%1").arg(QString::number(getTAR(operatingPoints, 0.001), 'f', 3))));
249 249 lines.append(qPrintable(QString("BC,0.01,%1").arg(QString::number(result = getTAR(operatingPoints, 0.01), 'f', 3))));
250 250  
  251 +
251 252 // Write SD & KDE
252 253 points = qMin(qMin(Max_Points, genuines.size()), impostors.size());
253 254 QList<double> sampledGenuineScores; sampledGenuineScores.reserve(points);
254 255 QList<double> sampledImpostorScores; sampledImpostorScores.reserve(points);
255   - for (int i=0; i<points; i++) {
256   - float genuineScore = genuines[double(i) / double(points-1) * double(genuines.size()-1)];
257   - float impostorScore = impostors[double(i) / double(points-1) * double(impostors.size()-1)];
258   - if (genuineScore == -std::numeric_limits<float>::max()) genuineScore = minGenuineScore;
259   - if (impostorScore == -std::numeric_limits<float>::max()) impostorScore = minImpostorScore;
260   - lines.append(QString("SD,%1,Genuine").arg(QString::number(genuineScore)));
261   - lines.append(QString("SD,%1,Impostor").arg(QString::number(impostorScore)));
262   - sampledGenuineScores.append(genuineScore);
263   - sampledImpostorScores.append(impostorScore);
  256 +
  257 + if (points > 1) {
  258 + for (int i=0; i<points; i++) {
  259 + float genuineScore = genuines[double(i) / double(points-1) * double(genuines.size()-1)];
  260 + float impostorScore = impostors[double(i) / double(points-1) * double(impostors.size()-1)];
  261 + if (genuineScore == -std::numeric_limits<float>::max()) genuineScore = minGenuineScore;
  262 + if (impostorScore == -std::numeric_limits<float>::max()) impostorScore = minImpostorScore;
  263 + lines.append(QString("SD,%1,Genuine").arg(QString::number(genuineScore)));
  264 + lines.append(QString("SD,%1,Impostor").arg(QString::number(impostorScore)));
  265 + sampledGenuineScores.append(genuineScore);
  266 + sampledImpostorScores.append(impostorScore);
  267 + }
264 268 }
265 269  
266 270 // Write Cumulative Match Characteristic (CMC) curve
267   - const int Max_Retrieval = 100;
  271 + const int Max_Retrieval = 200;
268 272 const int Report_Retrieval = 5;
  273 +
269 274 float reportRetrievalRate = -1;
270 275 for (int i=1; i<=Max_Retrieval; i++) {
271 276 int realizedReturns = 0, possibleReturns = 0;
... ... @@ -467,6 +472,8 @@ struct RPlot
467 472 }
468 473 };
469 474  
  475 +// Does not work if dataset folder starts with a number
  476 +
470 477 bool Plot(const QStringList &files, const br::File &destination, bool show)
471 478 {
472 479 qDebug("Plotting %d file(s) to %s", files.size(), qPrintable(destination));
... ...
openbr/openbr_plugin.cpp
... ... @@ -52,7 +52,7 @@ QString File::flat() const
52 52 const QVariant value = this->value(key);
53 53 if (value.isNull()) values.append(key);
54 54 else {
55   - if (QString(value.typeName()) == "QVariantList" || QString(value.typeName()) == "QStringList") {
  55 + if (QString(value.typeName()) == "QVariantList") {
56 56 QStringList variants;
57 57 foreach(const QVariant &variant, qvariant_cast<QVariantList>(value)) {
58 58 variants.append(QtUtils::toString(variant));
... ... @@ -137,7 +137,7 @@ QVariant File::value(const QString &amp;key) const
137 137  
138 138 QVariant File::parse(const QString &value)
139 139 {
140   - bool ok;
  140 + bool ok = false;
141 141 const QPointF point = QtUtils::toPoint(value, &ok);
142 142 if (ok) return point;
143 143 const QRectF rect = QtUtils::toRect(value, &ok);
... ... @@ -1003,7 +1003,7 @@ void Output::reformat(const FileList &amp;targetFiles, const FileList &amp;queryFiles, c
1003 1003 const int columns = targetFiles.size();
1004 1004 for (int i=0; i<rows; i++)
1005 1005 for (int j=0; j<columns; j++)
1006   - o->setRelative(m.at<float>(i,i), i, j);
  1006 + o->setRelative(m.at<float>(i,j), i, j);
1007 1007 }
1008 1008  
1009 1009 /* Output - protected methods */
... ...
openbr/openbr_plugin.h
... ... @@ -410,7 +410,7 @@ struct TemplateList : public QList&lt;Template&gt;
410 410 sum+=partitionSizes[i];
411 411 }
412 412  
413   - if (sum != first().size()) qFatal("Partition sizes do not span template matrices properly");
  413 + if (sum != first().size()) qFatal("Partition sizes %i do not span template matrices %i properly", sum, first().size());
414 414  
415 415 foreach (const Template &t, *this) {
416 416 int index = 0;
... ...
openbr/plugins/ct8.cpp
... ... @@ -11,9 +11,9 @@
11 11 #include <exception>
12 12 #include <string>
13 13 #include <vector>
14   -#include "openbr_internal.h"
15 14  
16   -#include "core/resource.h"
  15 +#include "openbr_internal.h"
  16 +#include "openbr/core/resource.h"
17 17  
18 18 using namespace cv;
19 19 using namespace br;
... ...
openbr/plugins/eigen3.cpp
... ... @@ -330,6 +330,7 @@ class LDATransform : public Transform
330 330 void train(const TemplateList &_trainingSet)
331 331 {
332 332 TemplateList trainingSet = TemplateList::relabel(_trainingSet);
  333 +
333 334 int instances = trainingSet.size();
334 335  
335 336 // Perform PCA dimensionality reduction
... ...
openbr/plugins/format.cpp
... ... @@ -317,6 +317,7 @@ BR_REGISTER(Format, maskFormat)
317 317 * \brief MATLAB <tt>.mat</tt> format.
318 318 * \author Josh Klontz \cite jklontz
319 319 * http://www.mathworks.com/help/pdf_doc/matlab/matfile_format.pdf
  320 + * \note matFormat is known not to work with compressed matrices
320 321 */
321 322 class matFormat : public Format
322 323 {
... ... @@ -324,12 +325,18 @@ class matFormat : public Format
324 325  
325 326 struct Element
326 327 {
  328 + // It is always best to cast integers to a Qt integer type, such as qint16 or quint32, when reading and writing.
  329 + // This ensures that you always know exactly what size integers you are reading and writing, no matter what the
  330 + // underlying platform and architecture the application happens to be running on.
  331 + // http://qt-project.org/doc/qt-4.8/datastreamformat.html
327 332 quint32 type, bytes;
328 333 QByteArray data;
329 334 Element() : type(0), bytes(0) {}
330 335 Element(QDataStream &stream)
331 336 : type(0), bytes(0)
332 337 {
  338 + // Read first 4 bytes into type (32 bit integer),
  339 + // specifying the type of data used
333 340 if (stream.readRawData((char*)&type, 4) != 4)
334 341 qFatal("Unexpected end of file.");
335 342  
... ... @@ -340,11 +347,16 @@ class matFormat : public Format
340 347 bytes = bytes >> 16;
341 348 } else {
342 349 // Regular format
  350 + // Read 4 bytes into bytes (32 bit integer),
  351 + // specifying the size of the element
343 352 if (stream.readRawData((char*)&bytes, 4) != 4)
344 353 qFatal("Unexpected end of file.");
345 354 }
346 355  
  356 + // Set the size of data to bytes
347 357 data.resize(bytes);
  358 +
  359 + // Read bytes amount of data from the file into data
348 360 if (int(bytes) != stream.readRawData(data.data(), bytes))
349 361 qFatal("Unexpected end of file.");
350 362  
... ... @@ -372,8 +384,9 @@ class matFormat : public Format
372 384 while (!f.atEnd()) {
373 385 Element element(f);
374 386  
375   - // miCOMPRESS
  387 + // miCOMPRESSED
376 388 if (element.type == 15) {
  389 + // Prepend the number of bytes to element.data
377 390 element.data.prepend((char*)&element.bytes, 4); // Qt zlib wrapper requires this to preallocate the buffer
378 391 QDataStream uncompressed(qUncompress(element.data));
379 392 element = Element(uncompressed);
... ...
openbr/plugins/stasm.cpp
... ... @@ -34,7 +34,7 @@ BR_REGISTER(Initializer, StasmInitializer)
34 34 * \author Scott Klum \cite sklum
35 35 */
36 36 // TODO: Use a global mutex to prevent concurrent calls to AsmSearchDll
37   -#if 0
  37 +
38 38 class StasmTransform : public UntrainableTransform
39 39 {
40 40 Q_OBJECT
... ... @@ -46,6 +46,9 @@ class StasmTransform : public UntrainableTransform
46 46  
47 47 void project(const Template &src, Template &dst) const
48 48 {
  49 + static QMutex mutex;
  50 + QMutexLocker locker(&mutex);
  51 +
49 52 int nlandmarks;
50 53 int landmarks[500];
51 54  
... ... @@ -68,7 +71,6 @@ class StasmTransform : public UntrainableTransform
68 71 };
69 72  
70 73 BR_REGISTER(Transform, StasmTransform)
71   -#endif
72 74  
73 75 } // namespace br
74 76  
... ...
openbr/plugins/validate.cpp
... ... @@ -52,8 +52,13 @@ class CrossValidateTransform : public MetaTransform
52 52 }
53 53  
54 54 void project(const Template &src, Template &dst) const
55   - {
56   - transforms[src.file.get<int>("Partition", 0)]->project(src, dst);
  55 + {
  56 + // If the src partition is greater than the number of training partitions,
  57 + // assume that projection should be done using the same training data for all partitions.
  58 + int partition = src.file.get<int>("Partition", 0);
  59 + if (partition >= transforms.size()-1) partition = 0;
  60 +
  61 + transforms[partition]->project(src, dst);
57 62 }
58 63  
59 64 void store(QDataStream &stream) const
... ...