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,9 +7,9 @@
7 * [FRGC](FRGC/README.md) 7 * [FRGC](FRGC/README.md)
8 * [LFW](LFW/LFW.md) 8 * [LFW](LFW/LFW.md)
9 * [MEDS](MEDS/README.md) 9 * [MEDS](MEDS/README.md)
  10 +* [MNIST](MNIST/README.md)
10 * [PCSO](PCSO/README.md) 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 Researchers should contact the respective owners of the other datasets in order to obtain a copy. 14 Researchers should contact the respective owners of the other datasets in order to obtain a copy.
15 The provided sigsets indicate how the images are expected to be arranged in directories, generally following the conventions established by the original authors. 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,9 +248,8 @@ struct AlgorithmCore
248 if (!partitionSizes.empty()) targetPartitions = targets.partition(partitionSizes); 248 if (!partitionSizes.empty()) targetPartitions = targets.partition(partitionSizes);
249 else targetPartitions.append(targets); 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 outputs[i]->setBlock(queryBlock, targetBlock); 251 outputs[i]->setBlock(queryBlock, targetBlock);
  252 +
254 distance->compare(targetPartitions[i], queryPartitions[i], outputs[i]); 253 distance->compare(targetPartitions[i], queryPartitions[i], outputs[i]);
255 254
256 Globals->currentStep += double(targets.size()) * double(queries.size()); 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,24 +248,29 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv)
248 lines.append(qPrintable(QString("BC,0.001,%1").arg(QString::number(getTAR(operatingPoints, 0.001), 'f', 3)))); 248 lines.append(qPrintable(QString("BC,0.001,%1").arg(QString::number(getTAR(operatingPoints, 0.001), 'f', 3))));
249 lines.append(qPrintable(QString("BC,0.01,%1").arg(QString::number(result = getTAR(operatingPoints, 0.01), 'f', 3)))); 249 lines.append(qPrintable(QString("BC,0.01,%1").arg(QString::number(result = getTAR(operatingPoints, 0.01), 'f', 3))));
250 250
  251 +
251 // Write SD & KDE 252 // Write SD & KDE
252 points = qMin(qMin(Max_Points, genuines.size()), impostors.size()); 253 points = qMin(qMin(Max_Points, genuines.size()), impostors.size());
253 QList<double> sampledGenuineScores; sampledGenuineScores.reserve(points); 254 QList<double> sampledGenuineScores; sampledGenuineScores.reserve(points);
254 QList<double> sampledImpostorScores; sampledImpostorScores.reserve(points); 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 // Write Cumulative Match Characteristic (CMC) curve 270 // Write Cumulative Match Characteristic (CMC) curve
267 - const int Max_Retrieval = 100; 271 + const int Max_Retrieval = 200;
268 const int Report_Retrieval = 5; 272 const int Report_Retrieval = 5;
  273 +
269 float reportRetrievalRate = -1; 274 float reportRetrievalRate = -1;
270 for (int i=1; i<=Max_Retrieval; i++) { 275 for (int i=1; i<=Max_Retrieval; i++) {
271 int realizedReturns = 0, possibleReturns = 0; 276 int realizedReturns = 0, possibleReturns = 0;
@@ -467,6 +472,8 @@ struct RPlot @@ -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 bool Plot(const QStringList &files, const br::File &destination, bool show) 477 bool Plot(const QStringList &files, const br::File &destination, bool show)
471 { 478 {
472 qDebug("Plotting %d file(s) to %s", files.size(), qPrintable(destination)); 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,7 +52,7 @@ QString File::flat() const
52 const QVariant value = this->value(key); 52 const QVariant value = this->value(key);
53 if (value.isNull()) values.append(key); 53 if (value.isNull()) values.append(key);
54 else { 54 else {
55 - if (QString(value.typeName()) == "QVariantList" || QString(value.typeName()) == "QStringList") { 55 + if (QString(value.typeName()) == "QVariantList") {
56 QStringList variants; 56 QStringList variants;
57 foreach(const QVariant &variant, qvariant_cast<QVariantList>(value)) { 57 foreach(const QVariant &variant, qvariant_cast<QVariantList>(value)) {
58 variants.append(QtUtils::toString(variant)); 58 variants.append(QtUtils::toString(variant));
@@ -137,7 +137,7 @@ QVariant File::value(const QString &amp;key) const @@ -137,7 +137,7 @@ QVariant File::value(const QString &amp;key) const
137 137
138 QVariant File::parse(const QString &value) 138 QVariant File::parse(const QString &value)
139 { 139 {
140 - bool ok; 140 + bool ok = false;
141 const QPointF point = QtUtils::toPoint(value, &ok); 141 const QPointF point = QtUtils::toPoint(value, &ok);
142 if (ok) return point; 142 if (ok) return point;
143 const QRectF rect = QtUtils::toRect(value, &ok); 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,7 +1003,7 @@ void Output::reformat(const FileList &amp;targetFiles, const FileList &amp;queryFiles, c
1003 const int columns = targetFiles.size(); 1003 const int columns = targetFiles.size();
1004 for (int i=0; i<rows; i++) 1004 for (int i=0; i<rows; i++)
1005 for (int j=0; j<columns; j++) 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 /* Output - protected methods */ 1009 /* Output - protected methods */
openbr/openbr_plugin.h
@@ -410,7 +410,7 @@ struct TemplateList : public QList&lt;Template&gt; @@ -410,7 +410,7 @@ struct TemplateList : public QList&lt;Template&gt;
410 sum+=partitionSizes[i]; 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 foreach (const Template &t, *this) { 415 foreach (const Template &t, *this) {
416 int index = 0; 416 int index = 0;
openbr/plugins/ct8.cpp
@@ -11,9 +11,9 @@ @@ -11,9 +11,9 @@
11 #include <exception> 11 #include <exception>
12 #include <string> 12 #include <string>
13 #include <vector> 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 using namespace cv; 18 using namespace cv;
19 using namespace br; 19 using namespace br;
openbr/plugins/eigen3.cpp
@@ -330,6 +330,7 @@ class LDATransform : public Transform @@ -330,6 +330,7 @@ class LDATransform : public Transform
330 void train(const TemplateList &_trainingSet) 330 void train(const TemplateList &_trainingSet)
331 { 331 {
332 TemplateList trainingSet = TemplateList::relabel(_trainingSet); 332 TemplateList trainingSet = TemplateList::relabel(_trainingSet);
  333 +
333 int instances = trainingSet.size(); 334 int instances = trainingSet.size();
334 335
335 // Perform PCA dimensionality reduction 336 // Perform PCA dimensionality reduction
openbr/plugins/format.cpp
@@ -317,6 +317,7 @@ BR_REGISTER(Format, maskFormat) @@ -317,6 +317,7 @@ BR_REGISTER(Format, maskFormat)
317 * \brief MATLAB <tt>.mat</tt> format. 317 * \brief MATLAB <tt>.mat</tt> format.
318 * \author Josh Klontz \cite jklontz 318 * \author Josh Klontz \cite jklontz
319 * http://www.mathworks.com/help/pdf_doc/matlab/matfile_format.pdf 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 class matFormat : public Format 322 class matFormat : public Format
322 { 323 {
@@ -324,12 +325,18 @@ class matFormat : public Format @@ -324,12 +325,18 @@ class matFormat : public Format
324 325
325 struct Element 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 quint32 type, bytes; 332 quint32 type, bytes;
328 QByteArray data; 333 QByteArray data;
329 Element() : type(0), bytes(0) {} 334 Element() : type(0), bytes(0) {}
330 Element(QDataStream &stream) 335 Element(QDataStream &stream)
331 : type(0), bytes(0) 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 if (stream.readRawData((char*)&type, 4) != 4) 340 if (stream.readRawData((char*)&type, 4) != 4)
334 qFatal("Unexpected end of file."); 341 qFatal("Unexpected end of file.");
335 342
@@ -340,11 +347,16 @@ class matFormat : public Format @@ -340,11 +347,16 @@ class matFormat : public Format
340 bytes = bytes >> 16; 347 bytes = bytes >> 16;
341 } else { 348 } else {
342 // Regular format 349 // Regular format
  350 + // Read 4 bytes into bytes (32 bit integer),
  351 + // specifying the size of the element
343 if (stream.readRawData((char*)&bytes, 4) != 4) 352 if (stream.readRawData((char*)&bytes, 4) != 4)
344 qFatal("Unexpected end of file."); 353 qFatal("Unexpected end of file.");
345 } 354 }
346 355
  356 + // Set the size of data to bytes
347 data.resize(bytes); 357 data.resize(bytes);
  358 +
  359 + // Read bytes amount of data from the file into data
348 if (int(bytes) != stream.readRawData(data.data(), bytes)) 360 if (int(bytes) != stream.readRawData(data.data(), bytes))
349 qFatal("Unexpected end of file."); 361 qFatal("Unexpected end of file.");
350 362
@@ -372,8 +384,9 @@ class matFormat : public Format @@ -372,8 +384,9 @@ class matFormat : public Format
372 while (!f.atEnd()) { 384 while (!f.atEnd()) {
373 Element element(f); 385 Element element(f);
374 386
375 - // miCOMPRESS 387 + // miCOMPRESSED
376 if (element.type == 15) { 388 if (element.type == 15) {
  389 + // Prepend the number of bytes to element.data
377 element.data.prepend((char*)&element.bytes, 4); // Qt zlib wrapper requires this to preallocate the buffer 390 element.data.prepend((char*)&element.bytes, 4); // Qt zlib wrapper requires this to preallocate the buffer
378 QDataStream uncompressed(qUncompress(element.data)); 391 QDataStream uncompressed(qUncompress(element.data));
379 element = Element(uncompressed); 392 element = Element(uncompressed);
openbr/plugins/stasm.cpp
@@ -34,7 +34,7 @@ BR_REGISTER(Initializer, StasmInitializer) @@ -34,7 +34,7 @@ BR_REGISTER(Initializer, StasmInitializer)
34 * \author Scott Klum \cite sklum 34 * \author Scott Klum \cite sklum
35 */ 35 */
36 // TODO: Use a global mutex to prevent concurrent calls to AsmSearchDll 36 // TODO: Use a global mutex to prevent concurrent calls to AsmSearchDll
37 -#if 0 37 +
38 class StasmTransform : public UntrainableTransform 38 class StasmTransform : public UntrainableTransform
39 { 39 {
40 Q_OBJECT 40 Q_OBJECT
@@ -46,6 +46,9 @@ class StasmTransform : public UntrainableTransform @@ -46,6 +46,9 @@ class StasmTransform : public UntrainableTransform
46 46
47 void project(const Template &src, Template &dst) const 47 void project(const Template &src, Template &dst) const
48 { 48 {
  49 + static QMutex mutex;
  50 + QMutexLocker locker(&mutex);
  51 +
49 int nlandmarks; 52 int nlandmarks;
50 int landmarks[500]; 53 int landmarks[500];
51 54
@@ -68,7 +71,6 @@ class StasmTransform : public UntrainableTransform @@ -68,7 +71,6 @@ class StasmTransform : public UntrainableTransform
68 }; 71 };
69 72
70 BR_REGISTER(Transform, StasmTransform) 73 BR_REGISTER(Transform, StasmTransform)
71 -#endif  
72 74
73 } // namespace br 75 } // namespace br
74 76
openbr/plugins/validate.cpp
@@ -52,8 +52,13 @@ class CrossValidateTransform : public MetaTransform @@ -52,8 +52,13 @@ class CrossValidateTransform : public MetaTransform
52 } 52 }
53 53
54 void project(const Template &src, Template &dst) const 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 void store(QDataStream &stream) const 64 void store(QDataStream &stream) const