Commit 8ccbcbe4edf5b79050d6312c9251bf73692c57b2

Authored by Scott Klum
2 parents 1fb3a925 3ad80556

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

CHANGELOG.md
1 1 0.3.0 - ??/??/??
2 2 ================
  3 +* YouTubeFacesDBTransform implements Dr. Wolf's experimental protocol
3 4  
4 5 0.2.0 - 2/23/13
5 6 ===============
... ...
sdk/core/bee.cpp
... ... @@ -42,8 +42,8 @@ FileList BEE::readSigset(const QString &sigset, bool ignoreMetadata)
42 42 QDomDocument doc(sigset);
43 43 QFile file(sigset);
44 44 bool success;
45   - success = file.open(QIODevice::ReadOnly); if (!success) qFatal("BEE::readSigset unable to open %s for reading.", qPrintable(sigset));
46   - success = doc.setContent(&file); if (!success) qFatal("BEE::readSigset unable to parse %s.", qPrintable(sigset));
  45 + success = file.open(QIODevice::ReadOnly); if (!success) qFatal("Unable to open %s for reading.", qPrintable(sigset));
  46 + success = doc.setContent(&file); if (!success) qFatal("Unable to parse %s.", qPrintable(sigset));
47 47 file.close();
48 48  
49 49 QDomElement docElem = doc.documentElement();
... ... @@ -75,7 +75,7 @@ FileList BEE::readSigset(const QString &sigset, bool ignoreMetadata)
75 75 }
76 76 }
77 77  
78   - if (file.isNull()) qFatal("BEE::readSigset empty file-name in %s.", qPrintable(sigset));
  78 + if (file.isNull()) qFatal("Empty file-name in %s.", qPrintable(sigset));
79 79 fileList.append(file);
80 80  
81 81 fileNode = fileNode.nextSibling();
... ... @@ -115,7 +115,7 @@ Mat readMatrix(const br::File &matrix)
115 115 if (matrix == "Matrix") {
116 116 const int size = matrix.getInt("Size");
117 117 const int step = matrix.getInt("Step", 1);
118   - if (size % step != 0) qFatal("bee.cpp readMatrix step does not divide size evenly.");
  118 + if (size % step != 0) qFatal("Step does not divide size evenly.");
119 119  
120 120 if (sizeof(T) == sizeof(BEE::Mask_t)) {
121 121 const bool selfSimilar = matrix.getBool("SelfSimilar");
... ... @@ -140,12 +140,12 @@ Mat readMatrix(const br::File &matrix)
140 140  
141 141 QFile file(matrix);
142 142 bool success = file.open(QFile::ReadOnly);
143   - if (!success) qFatal("bee.cpp readMatrix unable to open %s for reading.", qPrintable((QString)matrix));
  143 + if (!success) qFatal("Unable to open %s for reading.", qPrintable((QString)matrix));
144 144  
145 145 // Check format
146 146 QByteArray format = file.readLine();
147 147 bool isDistance = (format[0] == 'D');
148   - if (format[1] != '2') qFatal("bee.cpp readMatrix invalid matrix header.");
  148 + if (format[1] != '2') qFatal("Invalid matrix header.");
149 149  
150 150 // Skip sigset lines
151 151 file.readLine();
... ... @@ -160,7 +160,7 @@ Mat readMatrix(const br::File &matrix)
160 160 qint64 bytesExpected = (qint64)rows*(qint64)cols*(qint64)sizeof(T);
161 161 Mat m(rows, cols, OpenCVType<T,1>::make());
162 162 if (file.read((char*)m.data, bytesExpected) != bytesExpected)
163   - qFatal("bee.cpp readMatrix invalid matrix size.");
  163 + qFatal("Invalid matrix size.");
164 164 file.close();
165 165  
166 166 Mat result;
... ... @@ -182,17 +182,17 @@ Mat BEE::readMask(const br::File &amp;mask)
182 182 template <typename T>
183 183 void writeMatrix(const Mat &m, const QString &matrix, const QString &targetSigset, const QString &querySigset)
184 184 {
185   - if (m.type() != OpenCVType<T,1>::make()) qFatal("bee.cpp writeMatrix invalid matrix type.");
  185 + if (m.type() != OpenCVType<T,1>::make()) qFatal("Invalid matrix type.");
186 186  
187 187 int elemSize = sizeof(T);
188 188 QString matrixType;
189 189 if (elemSize == 1) matrixType = "B";
190 190 else if (elemSize == 4) matrixType = "F";
191   - else qFatal("bee.cpp writeMatrix invalid element size.\n");
  191 + else qFatal("Invalid element size.");
192 192  
193 193 char buff[4];
194 194 QFile file(matrix);
195   - bool success = file.open(QFile::WriteOnly); if (!success) qFatal("bee.cpp writeMatrix unable to open %s for writing.", qPrintable(matrix));
  195 + bool success = file.open(QFile::WriteOnly); if (!success) qFatal("Unable to open %s for writing.", qPrintable(matrix));
196 196 file.write("S2\n");
197 197 file.write(qPrintable(QFileInfo(targetSigset).fileName()));
198 198 file.write("\n");
... ... @@ -227,8 +227,8 @@ void BEE::makeMask(const QString &amp;targetInput, const QString &amp;queryInput, const
227 227 {
228 228 qDebug("Making mask from %s and %s to %s", qPrintable(targetInput), qPrintable(queryInput), qPrintable(mask));
229 229  
230   - FileList targetFiles = TemplateList::fromInput(targetInput).files();
231   - FileList queryFiles = TemplateList::fromInput(queryInput).files();
  230 + FileList targetFiles = TemplateList::fromGallery(targetInput).files();
  231 + FileList queryFiles = TemplateList::fromGallery(queryInput).files();
232 232 QList<float> targetLabels = targetFiles.labels();
233 233 QList<float> queryLabels = queryFiles.labels();
234 234 QList<int> targetPartitions = targetFiles.crossValidationPartitions();
... ... @@ -265,12 +265,12 @@ void BEE::combineMasks(const QStringList &amp;inputMasks, const QString &amp;outputMask,
265 265 bool AND = true;
266 266 if (method == "And") AND = true;
267 267 else if (method == "Or") AND = false;
268   - else qFatal("combineMasks invalid method");
  268 + else qFatal("Invalid method.");
269 269  
270 270 QList<Mat> masks;
271 271 foreach (const QString &inputMask, inputMasks)
272 272 masks.append(readMask(inputMask));
273   - if (masks.size() < 2) qFatal("BEE::mergeMasks expects at least two masks.");
  273 + if (masks.size() < 2) qFatal("Expected at least two masks.");
274 274  
275 275 const int rows = masks.first().rows;
276 276 const int columns = masks.first().cols;
... ... @@ -294,7 +294,7 @@ void BEE::combineMasks(const QStringList &amp;inputMasks, const QString &amp;outputMask,
294 294 break;
295 295 }
296 296 }
297   - if ((genuineCount != 0) && (imposterCount != 0)) qFatal("BEE::combinedMasks comparison is both a genuine and an imposter.");
  297 + if ((genuineCount != 0) && (imposterCount != 0)) qFatal("Comparison is both a genuine and an imposter.");
298 298  
299 299 Mask_t val;
300 300 if (genuineCount > 0) val = Match;
... ...
sdk/core/classify.cpp
... ... @@ -37,14 +37,14 @@ void br::EvalClassification(const QString &amp;predictedInput, const QString &amp;truthI
37 37 {
38 38 qDebug("Evaluating classification of %s against %s", qPrintable(predictedInput), qPrintable(truthInput));
39 39  
40   - TemplateList predicted(TemplateList::fromInput(predictedInput));
41   - TemplateList truth(TemplateList::fromInput(truthInput));
42   - if (predicted.size() != truth.size()) qFatal("br::EvalClassification input size mismatch.");
  40 + TemplateList predicted(TemplateList::fromGallery(predictedInput));
  41 + TemplateList truth(TemplateList::fromGallery(truthInput));
  42 + if (predicted.size() != truth.size()) qFatal("Input size mismatch.");
43 43  
44 44 QHash<int, Counter> counters;
45 45 for (int i=0; i<predicted.size(); i++) {
46 46 if (predicted[i].file.name != truth[i].file.name)
47   - qFatal("br::EvalClassification input order mismatch.");
  47 + qFatal("Input order mismatch.");
48 48  
49 49 const int trueLabel = truth[i].file.label();
50 50 const int predictedLabel = predicted[i].file.label();
... ... @@ -83,15 +83,15 @@ void br::EvalRegression(const QString &amp;predictedInput, const QString &amp;truthInput
83 83 {
84 84 qDebug("Evaluating regression of %s against %s", qPrintable(predictedInput), qPrintable(truthInput));
85 85  
86   - const TemplateList predicted(TemplateList::fromInput(predictedInput));
87   - const TemplateList truth(TemplateList::fromInput(truthInput));
88   - if (predicted.size() != truth.size()) qFatal("br::EvalRegression input size mismatch.");
  86 + const TemplateList predicted(TemplateList::fromGallery(predictedInput));
  87 + const TemplateList truth(TemplateList::fromGallery(truthInput));
  88 + if (predicted.size() != truth.size()) qFatal("Input size mismatch.");
89 89  
90 90 float rmsError = 0;
91 91 QStringList truthValues, predictedValues;
92 92 for (int i=0; i<predicted.size(); i++) {
93 93 if (predicted[i].file.name != truth[i].file.name)
94   - qFatal("br::EvalRegression input order mismatch.");
  94 + qFatal("Input order mismatch.");
95 95 rmsError += pow(predicted[i].file.label()-truth[i].file.label(), 2.f);
96 96 truthValues.append(QString::number(truth[i].file.label()));
97 97 predictedValues.append(QString::number(predicted[i].file.label()));
... ...
sdk/core/cluster.cpp
... ... @@ -90,7 +90,7 @@ Neighborhood getNeighborhood(const QStringList &amp;simmats)
90 90 float globalMin = std::numeric_limits<float>::max();
91 91 int numGalleries = (int)sqrt((float)simmats.size());
92 92 if (numGalleries*numGalleries != simmats.size())
93   - qFatal("cluser.cpp readGalleries incorrect number of similarity matrices.");
  93 + qFatal("Incorrect number of similarity matrices.");
94 94  
95 95 // Process each simmat
96 96 for (int i=0; i<numGalleries; i++) {
... ... @@ -104,7 +104,7 @@ Neighborhood getNeighborhood(const QStringList &amp;simmats)
104 104 currentRows = m.rows;
105 105 allNeighbors.resize(currentRows);
106 106 }
107   - if (currentRows != m.rows) qFatal("cluster.cpp::getNeighborhood row count mismatch.");
  107 + if (currentRows != m.rows) qFatal("Row count mismatch.");
108 108  
109 109 // Get data row by row
110 110 for (int k=0; k<m.rows; k++) {
... ... @@ -278,7 +278,7 @@ void br::EvalClustering(const QString &amp;csv, const QString &amp;input)
278 278 {
279 279 qDebug("Evaluating %s against %s", qPrintable(csv), qPrintable(input));
280 280  
281   - QList<float> labels = TemplateList::fromInput(input).files().labels();
  281 + QList<float> labels = TemplateList::fromGallery(input).files().labels();
282 282  
283 283 QHash<int, int> labelToIndex;
284 284 int nClusters = 0;
... ... @@ -322,7 +322,7 @@ br::Clusters br::ReadClusters(const QString &amp;csv)
322 322 Clusters clusters;
323 323 QFile file(csv);
324 324 bool success = file.open(QFile::ReadOnly);
325   - if (!success) qFatal("br::ReadClusters failed to open %s for reading.", qPrintable(csv));
  325 + if (!success) qFatal("Failed to open %s for reading.", qPrintable(csv));
326 326 QStringList lines = QString(file.readAll()).split("\n");
327 327 file.close();
328 328  
... ... @@ -332,7 +332,7 @@ br::Clusters br::ReadClusters(const QString &amp;csv)
332 332 foreach (const QString &id, ids) {
333 333 bool ok;
334 334 cluster.append(id.toInt(&ok));
335   - if (!ok) qFatal("br::ReadClusters non-interger id.");
  335 + if (!ok) qFatal("Non-interger id.");
336 336 }
337 337 clusters.append(cluster);
338 338 }
... ... @@ -343,7 +343,7 @@ void br::WriteClusters(const Clusters &amp;clusters, const QString &amp;csv)
343 343 {
344 344 QFile file(csv);
345 345 bool success = file.open(QFile::WriteOnly);
346   - if (!success) qFatal("br::WriteClusters failed to open %s for writing.", qPrintable(csv));
  346 + if (!success) qFatal("Failed to open %s for writing.", qPrintable(csv));
347 347  
348 348 foreach (Cluster cluster, clusters) {
349 349 if (cluster.empty()) continue;
... ...
sdk/core/common.cpp
... ... @@ -33,7 +33,7 @@ QList&lt;int&gt; Common::RandSample(int n, int max, int min, bool unique)
33 33  
34 34 QList<int> samples; samples.reserve(n);
35 35 int range = max-min;
36   - if (range <= 0) qFatal("Common::RandSample non-positive range.");
  36 + if (range <= 0) qFatal("Non-positive range.");
37 37 if (unique && (n >= range)) {
38 38 for (int i=min; i<max; i++)
39 39 samples.append(i);
... ...
sdk/core/core.cpp
... ... @@ -40,7 +40,7 @@ struct AlgorithmCore
40 40  
41 41 void train(const File &input, const QString &model)
42 42 {
43   - TemplateList data(TemplateList::fromInput(input));
  43 + TemplateList data(TemplateList::fromGallery(input));
44 44  
45 45 if (transform.isNull()) qFatal("Null transform.");
46 46 qDebug("%d training files", data.size());
... ... @@ -118,7 +118,7 @@ struct AlgorithmCore
118 118 if (!fileList.isEmpty() && gallery.contains("cache"))
119 119 return fileList;
120 120  
121   - const TemplateList i(TemplateList::fromInput(input));
  121 + const TemplateList i(TemplateList::fromGallery(input));
122 122 if (i.isEmpty()) return fileList; // Nothing to enroll
123 123  
124 124 if (transform.isNull()) qFatal("Null transform.");
... ... @@ -280,9 +280,12 @@ public:
280 280 if (algorithm.isEmpty()) qFatal("No default algorithm set.");
281 281  
282 282 if (!algorithms.contains(algorithm)) {
  283 + // Some algorithms are recursive, so we need to construct them outside the lock.
  284 + QSharedPointer<AlgorithmCore> algorithmCore(new AlgorithmCore(algorithm));
  285 +
283 286 algorithmsLock.lock();
284 287 if (!algorithms.contains(algorithm))
285   - algorithms.insert(algorithm, QSharedPointer<AlgorithmCore>(new AlgorithmCore(algorithm)));
  288 + algorithms.insert(algorithm, algorithmCore);
286 289 algorithmsLock.unlock();
287 290 }
288 291  
... ...
sdk/core/fuse.cpp
... ... @@ -60,7 +60,7 @@ static void normalizeMatrix(Mat &amp;matrix, const Mat &amp;mask, const QString &amp;method)
60 60 }
61 61 }
62 62 } else if (method == "ZScore") {
63   - if (stddev == 0) qFatal("fuse.cpp normalizeMatrix stddev is 0.");
  63 + if (stddev == 0) qFatal("Stddev is 0.");
64 64 for (int i=0; i<matrix.rows; i++) {
65 65 for (int j=0; j<matrix.cols; j++) {
66 66 if (mask.at<BEE::Mask_t>(i,j) == BEE::DontCare) continue;
... ... @@ -71,7 +71,7 @@ static void normalizeMatrix(Mat &amp;matrix, const Mat &amp;mask, const QString &amp;method)
71 71 }
72 72 }
73 73 } else {
74   - qFatal("fuse.cpp normalizeMatrix invalid normalization method %s.", qPrintable(method));
  74 + qFatal("Invalid normalization method %s.", qPrintable(method));
75 75 }
76 76 }
77 77  
... ... @@ -81,8 +81,8 @@ void br::Fuse(const QStringList &amp;inputSimmats, const QString &amp;mask, const QStrin
81 81 QList<Mat> matrices;
82 82 foreach (const QString &simmat, inputSimmats)
83 83 matrices.append(BEE::readSimmat(simmat));
84   - if ((matrices.size() < 2) && (fusion != "None")) qFatal("br::Fuse expected at least two similarity matrices.");
85   - if ((matrices.size() > 1) && (fusion == "None")) qFatal("mm:Fuse expected exactly one similarity matrix.");
  84 + if ((matrices.size() < 2) && (fusion != "None")) qFatal("Expected at least two similarity matrices.");
  85 + if ((matrices.size() > 1) && (fusion == "None")) qFatal("Expected exactly one similarity matrix.");
86 86 Mat matrix_mask = BEE::readMask(mask);
87 87  
88 88 for (int i=0; i<matrices.size(); i++)
... ... @@ -107,27 +107,27 @@ void br::Fuse(const QStringList &amp;inputSimmats, const QString &amp;mask, const QStrin
107 107 bool ok;
108 108 for (int k=0; k<matrices.size(); k++) {
109 109 float weight = words[k].toFloat(&ok);
110   - if (!ok) qFatal("br::Fuse non-numerical weight %s.", qPrintable(words[k]));
  110 + if (!ok) qFatal("Non-numerical weight %s.", qPrintable(words[k]));
111 111 weights.append(weight);
112 112 }
113 113 } else {
114   - qFatal("br::Fuse number of weights does not match number of similarity matrices.");
  114 + qFatal("Number of weights does not match number of similarity matrices.");
115 115 }
116 116  
117 117 addWeighted(matrices[0], weights[0], matrices[1], weights[1], 0, fused);
118 118 for (int i=2; i<matrices.size(); i++)
119 119 addWeighted(fused, 1, matrices[i], weights[i], 0, fused);
120 120 } else if (fusion == "Replace") {
121   - if (matrices.size() != 2) qFatal("br::Fuse Replace fusion requires exactly two matrices.");
  121 + if (matrices.size() != 2) qFatal("Replace fusion requires exactly two matrices.");
122 122 fused = matrices.first().clone();
123 123 matrices.last().copyTo(fused, matrix_mask != BEE::DontCare);
124 124 } else if (fusion == "Difference") {
125   - if (matrices.size() != 2) qFatal("br::Fuse Difference fusion requires exactly two matrices.");
  125 + if (matrices.size() != 2) qFatal("Difference fusion requires exactly two matrices.");
126 126 subtract(matrices[0], matrices[1], fused);
127 127 } else if (fusion == "None") {
128 128 fused = matrices[0];
129 129 } else {
130   - qFatal("br::Fuse invalid fusion method %s.", qPrintable(fusion));
  130 + qFatal("Invalid fusion method %s.", qPrintable(fusion));
131 131 }
132 132  
133 133 BEE::writeSimmat(fused, outputSimmat);
... ...
sdk/core/opencvutils.cpp
... ... @@ -55,7 +55,7 @@ void OpenCVUtils::saveImage(const Mat &amp;src, const QString &amp;file)
55 55  
56 56 Mat draw;
57 57 cvtUChar(src, draw);
58   - bool success = imwrite(file.toStdString(), draw); if (!success) qFatal("OpenCVUtils::saveImage failed to save %s", qPrintable(file));
  58 + bool success = imwrite(file.toStdString(), draw); if (!success) qFatal("Failed to save %s", qPrintable(file));
59 59 }
60 60  
61 61 void OpenCVUtils::showImage(const Mat &src, const QString &window, bool waitKey)
... ... @@ -112,7 +112,7 @@ Mat OpenCVUtils::toMat(const QList&lt;float&gt; &amp;src, int rows)
112 112 {
113 113 if (rows == -1) rows = src.size();
114 114 int columns = src.isEmpty() ? 0 : src.size() / rows;
115   - if (rows*columns != src.size()) qFatal("OpenCVUtils::toMat invalid matrix size.");
  115 + if (rows*columns != src.size()) qFatal("Invalid matrix size.");
116 116 Mat dst(rows, columns, CV_32FC1);
117 117 for (int i=0; i<src.size(); i++)
118 118 dst.at<float>(i/columns,i%columns) = src[i];
... ... @@ -131,7 +131,7 @@ Mat OpenCVUtils::toMat(const QList&lt;Mat&gt; &amp;src)
131 131 for (int i=0; i<rows; i++) {
132 132 const Mat &m = src[i];
133 133 if ((m.total() != total) || (m.type() != type) || !m.isContinuous())
134   - qFatal("OpenCVUtils::toMat invalid matrix.");
  134 + qFatal("Invalid matrix.");
135 135 memcpy(dst.ptr(i), m.ptr(), total * src.first().elemSize());
136 136 }
137 137 return dst;
... ... @@ -149,7 +149,7 @@ Mat OpenCVUtils::toMatByRow(const QList&lt;Mat&gt; &amp;src)
149 149 int row = 0;
150 150 foreach (const Mat &m, src) {
151 151 if ((m.cols != cols) || (m.type() != type) || (!m.isContinuous()))
152   - qFatal("OpenCVUtils::toMatByRow invalid matrix.");
  152 + qFatal("Invalid matrix.");
153 153 memcpy(dst.ptr(row), m.ptr(), m.rows*m.cols*m.elemSize());
154 154 row += m.rows;
155 155 }
... ... @@ -167,7 +167,7 @@ QString OpenCVUtils::elemToString(const Mat &amp;m, int r, int c)
167 167 case CV_32S: return QString::number(m.at<qint32>(r,c));
168 168 case CV_32F: return QString::number(m.at<float>(r,c));
169 169 case CV_64F: return QString::number(m.at<double>(r,c));
170   - default: qFatal("OpenCVUtils::elemToString unknown matrix depth");
  170 + default: qFatal("Unknown matrix depth");
171 171 }
172 172 return "?";
173 173 }
... ... @@ -183,7 +183,7 @@ float OpenCVUtils::elemToFloat(const Mat &amp;m, int r, int c)
183 183 case CV_32S: return float(m.at<qint32>(r,c));
184 184 case CV_32F: return float(m.at<float>(r,c));
185 185 case CV_64F: return float(m.at<double>(r,c));
186   - default: qFatal("OpenCVUtils::elemToFloat unknown matrix depth");
  186 + default: qFatal("Unknown matrix depth");
187 187 }
188 188 return 0;
189 189 }
... ... @@ -300,10 +300,9 @@ QDataStream &amp;operator&lt;&lt;(QDataStream &amp;stream, const Mat &amp;m)
300 300 int len = rows*cols*m.elemSize();
301 301 stream << len;
302 302 if (len > 0) {
303   - if (!m.isContinuous()) qFatal("opencvutils.cpp operator<< Mat can't serialize non-continuous matrices.");
  303 + if (!m.isContinuous()) qFatal("Can't serialize non-continuous matrices.");
304 304 int written = stream.writeRawData((const char*)m.data, len);
305   -
306   - if (written != len) qFatal("opencvutils.cpp operator<< Mat serialization failure.");
  305 + if (written != len) qFatal("Serialization failure.");
307 306 }
308 307 return stream;
309 308 }
... ...
sdk/core/plot.cpp
... ... @@ -309,7 +309,7 @@ struct RPlot
309 309  
310 310 RPlot(QStringList files, const br::File &destination, bool isEvalFormat = true)
311 311 {
312   - if (files.isEmpty()) qFatal("RPlot::RPlot() empty file list.");
  312 + if (files.isEmpty()) qFatal("Empty file list.");
313 313 qSort(files.begin(), files.end(), sortFiles);
314 314  
315 315 // Parse destination
... ... @@ -320,7 +320,7 @@ struct RPlot
320 320  
321 321 file.setFileName(basename+".R");
322 322 bool success = file.open(QFile::WriteOnly);
323   - if (!success) qFatal("RPlot::RPlot() failed to open %s for writing.", qPrintable(file.fileName()));
  323 + if (!success) qFatal("Failed to open %s for writing.", qPrintable(file.fileName()));
324 324  
325 325 file.write("# Load libraries\n"
326 326 "library(ggplot2)\n"
... ...
sdk/core/qtutils.cpp
... ... @@ -44,7 +44,7 @@ QStringList QtUtils::getFiles(QDir dir, bool recursive)
44 44  
45 45 foreach (const QString &folder, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
46 46 QDir subdir(dir);
47   - bool success = subdir.cd(folder); if (!success) qFatal("QtUtils::getFiles cd failure.");
  47 + bool success = subdir.cd(folder); if (!success) qFatal("cd failure.");
48 48 files.append(getFiles(subdir, true));
49 49 }
50 50 return files;
... ... @@ -74,7 +74,7 @@ QStringList QtUtils::readLines(const QString &amp;file)
74 74 void QtUtils::readFile(const QString &file, QStringList &lines)
75 75 {
76 76 QFile f(file);
77   - if (!f.open(QFile::ReadOnly)) qFatal("QtUtils::readFile unable to open %s for reading.", qPrintable(file));
  77 + if (!f.open(QFile::ReadOnly)) qFatal("Unable to open %s for reading.", qPrintable(file));
78 78 lines = QString(f.readAll()).split('\n', QString::SkipEmptyParts);
79 79 for (int i=0; i<lines.size(); i++)
80 80 lines[i] = lines[i].simplified();
... ... @@ -84,7 +84,7 @@ void QtUtils::readFile(const QString &amp;file, QStringList &amp;lines)
84 84 void QtUtils::readFile(const QString &file, QByteArray &data, bool uncompress)
85 85 {
86 86 QFile f(file);
87   - if (!f.open(QFile::ReadOnly)) qFatal("QtUtils::readFile unable to open %s for reading.", qPrintable(file));
  87 + if (!f.open(QFile::ReadOnly)) qFatal("Unable to open %s for reading.", qPrintable(file));
88 88 data = f.readAll();
89 89 if (uncompress) data = qUncompress(data);
90 90 f.close();
... ... @@ -112,7 +112,7 @@ void QtUtils::writeFile(const QString &amp;file, const QByteArray &amp;data, int compres
112 112 QFile f(file);
113 113 touchDir(f);
114 114 if (!f.open(QFile::WriteOnly))
115   - qFatal("QtUtils::writeFile failed to open %s for writing.", qPrintable(file));
  115 + qFatal("Failed to open %s for writing.", qPrintable(file));
116 116 f.write(contents);
117 117 f.close();
118 118 }
... ... @@ -139,7 +139,7 @@ void QtUtils::emptyDir(QDir &amp;dir)
139 139 {
140 140 foreach (const QString &folder, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks)) {
141 141 QDir subdir(dir);
142   - bool success = subdir.cd(folder); if (!success) qFatal("QtUtils::emptyDir cd failure.");
  142 + bool success = subdir.cd(folder); if (!success) qFatal("cd failure.");
143 143 emptyDir(subdir);
144 144 }
145 145  
... ... @@ -163,28 +163,28 @@ QString QtUtils::find(const QString &amp;file, const QString &amp;alt)
163 163 {
164 164 if (QFileInfo(file).exists()) return file;
165 165 if (QFileInfo(alt).exists()) return alt;
166   - qFatal("QtUtils::find can't find file %s or alt %s\n", qPrintable(file), qPrintable(alt));
  166 + qFatal("Can't find file %s or alt %s\n", qPrintable(file), qPrintable(alt));
167 167 return "";
168 168 }
169 169  
170 170 bool QtUtils::toBool(const QString &string)
171 171 {
172 172 bool ok;
173   - bool result = (bool)string.toInt(&ok); if (!ok) qFatal("QtUtils::toBool expected integer value, got %s.", qPrintable(string));
  173 + bool result = (bool)string.toInt(&ok); if (!ok) qFatal("Expected integer value, got %s.", qPrintable(string));
174 174 return result;
175 175 }
176 176  
177 177 int QtUtils::toInt(const QString &string)
178 178 {
179 179 bool ok;
180   - int result = string.toInt(&ok); if (!ok) qFatal("QtUtils::toInt expected integer value, got %s.", qPrintable(string));
  180 + int result = string.toInt(&ok); if (!ok) qFatal("Expected integer value, got %s.", qPrintable(string));
181 181 return result;
182 182 }
183 183  
184 184 float QtUtils::toFloat(const QString &string)
185 185 {
186 186 bool ok;
187   - float result = string.toFloat(&ok); if (!ok) qFatal("QtUtils::toFloat expected floating point value, got %s.", qPrintable(string));
  187 + float result = string.toFloat(&ok); if (!ok) qFatal("Expected floating point value, got %s.", qPrintable(string));
188 188 return result;
189 189 }
190 190  
... ... @@ -194,7 +194,7 @@ QList&lt;float&gt; QtUtils::toFloats(const QStringList &amp;strings)
194 194 bool ok;
195 195 foreach (const QString &string, strings) {
196 196 floats.append(string.toFloat(&ok));
197   - if (!ok) qFatal("QtUtils::toFloats failed to convert %s to floating point format.", qPrintable(string));
  197 + if (!ok) qFatal("Failed to convert %s to floating point format.", qPrintable(string));
198 198 }
199 199 return floats;
200 200 }
... ... @@ -239,13 +239,13 @@ QStringList QtUtils::parse(QString args, char split)
239 239 } else if ((args[i] == '(') || (args[i] == '[') || (args[i] == '<') || (args[i] == '{')) {
240 240 subexpressions.push(args[i]);
241 241 } else if (args[i] == ')') {
242   - if (subexpressions.pop() != '(') qFatal("QtUtils::parse unexpected ')'.");
  242 + if (subexpressions.pop() != '(') qFatal("Unexpected ')'.");
243 243 } else if (args[i] == ']') {
244   - if (subexpressions.pop() != '[') qFatal("QtUtils::parse unexpected ']'.");
  244 + if (subexpressions.pop() != '[') qFatal("Unexpected ']'.");
245 245 } else if (args[i] == '>') {
246   - if (subexpressions.pop() != '<') qFatal("QtUtils::parse unexpected '>'.");
  246 + if (subexpressions.pop() != '<') qFatal("Unexpected '>'.");
247 247 } else if (args[i] == '}') {
248   - if (subexpressions.pop() != '{') qFatal("QtUtils::parse unexpected '}'.");
  248 + if (subexpressions.pop() != '{') qFatal("Unexpected '}'.");
249 249 } else if (subexpressions.isEmpty() && (args[i] == split)) {
250 250 words.append(args.mid(start, i-start).trimmed());
251 251 start = i+1;
... ...
sdk/openbr.cpp
... ... @@ -204,7 +204,7 @@ void br_read_line(int *argc, const char ***argv)
204 204  
205 205 void br_reformat(const char *target_input, const char *query_input, const char *simmat, const char *output)
206 206 {
207   - Output::reformat(TemplateList::fromInput(target_input).files(), TemplateList::fromInput(query_input).files(), simmat, output);
  207 + Output::reformat(TemplateList::fromGallery(target_input).files(), TemplateList::fromGallery(query_input).files(), simmat, output);
208 208 }
209 209  
210 210 const char *br_scratch_path()
... ...
sdk/openbr_plugin.cpp
... ... @@ -95,6 +95,11 @@ QList&lt;File&gt; File::split(const QString &amp;separator) const
95 95 return files;
96 96 }
97 97  
  98 +QString File::resolved() const
  99 +{
  100 + return exists() ? name : Globals->path + "/" + name;
  101 +}
  102 +
98 103 bool File::contains(const QString &key) const
99 104 {
100 105 return m_metadata.contains(key) || Globals->contains(key);
... ... @@ -150,7 +155,7 @@ void File::set(const QString &amp;key, const QVariant &amp;value)
150 155  
151 156 QVariant File::get(const QString &key) const
152 157 {
153   - if (!contains(key)) qFatal("File::get missing key: %s", qPrintable(key));
  158 + if (!contains(key)) qFatal("Missing key: %s", qPrintable(key));
154 159 return value(key);
155 160 }
156 161  
... ... @@ -177,9 +182,9 @@ void File::setBool(const QString &amp;key, bool value)
177 182  
178 183 int File::getInt(const QString &key) const
179 184 {
180   - if (!contains(key)) qFatal("File::getInt missing key: %s", qPrintable(key));
  185 + if (!contains(key)) qFatal("Missing key: %s", qPrintable(key));
181 186 bool ok; int result = value(key).toInt(&ok);
182   - if (!ok) qFatal("File::getInt invalid conversion from: %s", qPrintable(getString(key)));
  187 + if (!ok) qFatal("Invalid conversion from: %s", qPrintable(getString(key)));
183 188 return result;
184 189 }
185 190  
... ... @@ -193,9 +198,9 @@ int File::getInt(const QString &amp;key, int defaultValue) const
193 198  
194 199 float File::getFloat(const QString &key) const
195 200 {
196   - if (!contains(key)) qFatal("File::getFloat missing key: %s", qPrintable(key));
  201 + if (!contains(key)) qFatal("Missing key: %s", qPrintable(key));
197 202 bool ok; float result = value(key).toFloat(&ok);
198   - if (!ok) qFatal("File::getFloat invalid conversion from: %s", qPrintable(getString(key)));
  203 + if (!ok) qFatal("Invalid conversion from: %s", qPrintable(getString(key)));
199 204 return result;
200 205 }
201 206  
... ... @@ -209,7 +214,7 @@ float File::getFloat(const QString &amp;key, float defaultValue) const
209 214  
210 215 QString File::getString(const QString &key) const
211 216 {
212   - if (!contains(key)) qFatal("File::getString missing key: %s", qPrintable(key));
  217 + if (!contains(key)) qFatal("Missing key: %s", qPrintable(key));
213 218 return value(key).toString();
214 219 }
215 220  
... ... @@ -440,14 +445,14 @@ QDataStream &amp;br::operator&gt;&gt;(QDataStream &amp;stream, Template &amp;t)
440 445 }
441 446  
442 447 /* TemplateList - public methods */
443   -TemplateList TemplateList::fromInput(const br::File &input)
  448 +TemplateList TemplateList::fromGallery(const br::File &gallery)
444 449 {
445 450 TemplateList templates;
446 451  
447   - foreach (const br::File &file, input.split()) {
  452 + foreach (const br::File &file, gallery.split()) {
448 453 QScopedPointer<Gallery> i(Gallery::make(file));
449 454 TemplateList newTemplates = i->read();
450   - const int crossValidate = input.getInt("crossValidate");
  455 + const int crossValidate = gallery.getInt("crossValidate");
451 456 if (crossValidate > 0) srand(0);
452 457  
453 458 // If file is a Format not a Gallery
... ... @@ -456,13 +461,13 @@ TemplateList TemplateList::fromInput(const br::File &amp;input)
456 461  
457 462 // Propogate metadata
458 463 for (int i=0; i<newTemplates.size(); i++) {
459   - newTemplates[i].file.append(input.localMetadata());
  464 + newTemplates[i].file.append(gallery.localMetadata());
460 465 newTemplates[i].file.append(file.localMetadata());
461   - newTemplates[i].file.insert("Input_Index", i+templates.size());
  466 + newTemplates[i].file.insert("Index", i+templates.size());
462 467 if (crossValidate > 0) newTemplates[i].file.insert("Cross_Validation_Partition", rand()%crossValidate);
463 468 }
464 469  
465   - if (!templates.isEmpty() && input.getBool("merge")) {
  470 + if (!templates.isEmpty() && gallery.getBool("merge")) {
466 471 if (newTemplates.size() != templates.size())
467 472 qFatal("Inputs must be the same size in order to merge.");
468 473 for (int i=0; i<templates.size(); i++)
... ... @@ -652,7 +657,7 @@ void Object::setProperty(const QString &amp;name, const QString &amp;value)
652 657  
653 658 QVariant variant;
654 659 if (type.startsWith("QList<") && type.endsWith(">")) {
655   - if (!value.startsWith('[')) qFatal("Object::setProperty expected a list.");
  660 + if (!value.startsWith('[')) qFatal("Expected a list.");
656 661 const QStringList strings = parse(value.mid(1, value.size()-2));
657 662  
658 663 if (type == "QList<float>") {
... ... @@ -1014,6 +1019,11 @@ void MatrixOutput::initialize(const FileList &amp;targetFiles, const FileList &amp;query
1014 1019 data.create(queryFiles.size(), targetFiles.size(), CV_32FC1);
1015 1020 }
1016 1021  
  1022 +MatrixOutput *MatrixOutput::make(const FileList &targetFiles, const FileList &queryFiles)
  1023 +{
  1024 + return dynamic_cast<MatrixOutput*>(Output::make(".Matrix", targetFiles, queryFiles));
  1025 +}
  1026 +
1017 1027 /* MatrixOutput - protected methods */
1018 1028 QString MatrixOutput::toString(int row, int column) const
1019 1029 {
... ...
sdk/openbr_plugin.h
... ... @@ -126,7 +126,7 @@ void reset_##NAME() { NAME = DEFAULT; }
126 126 * path | QString | Resolve complete file paths from file names
127 127 * enrollAll | bool | Enroll zero or more templates per file
128 128 * separator | QString | Seperate #name into multiple files
129   - * Input_Index | int | Index of a template in a template list
  129 + * Index | int | Index of a template in a template list
130 130 * Label | float | Classification/Regression class
131 131 * Confidence | float | Classification/Regression quality
132 132 * FTE | bool | Failure to enroll
... ... @@ -153,7 +153,7 @@ struct BR_EXPORT File
153 153 File(const QString &file) { init(file); } /*!< \brief Construct a file from a string. */
154 154 File(const QString &file, const QVariant &label) { init(file); insert("Label", label); } /*!< \brief Construct a file from a string and assign a label. */
155 155 File(const char *file) { init(file); } /*!< \brief Construct a file from a c-style string. */
156   - operator QString() const { return name; } /*!< \brief Returns #name. */
  156 + inline operator QString() const { return name; } /*!< \brief Returns #name. */
157 157 QString flat() const; /*!< \brief A stringified version of the file with metadata. */
158 158 QString hash() const; /*!< \brief A hash of the file. */
159 159 inline void clear() { name.clear(); m_metadata.clear(); } /*!< \brief Clears the file's name and metadata. */
... ... @@ -187,6 +187,7 @@ struct BR_EXPORT File
187 187 inline QString baseName() const { const QString baseName = QFileInfo(name).baseName();
188 188 return baseName.isEmpty() ? QDir(name).dirName() : baseName; } /*!< \brief Returns the file's base name. */
189 189 inline QString suffix() const { return QFileInfo(name).suffix(); } /*!< \brief Returns the file's extension. */
  190 + QString resolved() const; /*!< \brief Returns name prepended with Globals->path if name does not exist. */
190 191  
191 192 bool contains(const QString &key) const; /*!< \brief Returns \c true if the key has an associated value, \c false otherwise. */
192 193 QVariant value(const QString &key) const; /*!< \brief Returns the value for the specified key. */
... ... @@ -276,7 +277,7 @@ struct Template : public QList&lt;cv::Mat&gt;
276 277 Template(const cv::Mat &mat) { append(mat); } /*!< \brief Append a matrix. */
277 278  
278 279 inline const cv::Mat &m() const { static const cv::Mat NullMatrix;
279   - return isEmpty() ? qFatal("Template::m() empty template."), NullMatrix : last(); } /*!< \brief Idiom to treat the template as a matrix. */
  280 + return isEmpty() ? qFatal("Empty template."), NullMatrix : last(); } /*!< \brief Idiom to treat the template as a matrix. */
280 281 inline cv::Mat &m() { return isEmpty() ? append(cv::Mat()), last() : last(); } /*!< \brief Idiom to treat the template as a matrix. */
281 282 inline cv::Mat &operator=(const cv::Mat &other) { return m() = other; } /*!< \brief Idiom to treat the template as a matrix. */
282 283 inline operator const cv::Mat&() const { return m(); } /*!< \brief Idiom to treat the template as a matrix. */
... ... @@ -330,9 +331,10 @@ struct TemplateList : public QList&lt;Template&gt;
330 331  
331 332 TemplateList() : uniform(false) {}
332 333 TemplateList(const QList<Template> &templates) : uniform(false) { append(templates); } /*!< \brief Initialize the template list from another template list. */
333   - TemplateList(const QList<File> &files) : uniform(false) { foreach (const File &file, files) append(file); }
334   - BR_EXPORT static TemplateList fromInput(const File &input); /*!< \brief Create a template list from a br::Input. */
  334 + TemplateList(const QList<File> &files) : uniform(false) { foreach (const File &file, files) append(file); } /*!< \brief Initialize the template list from a file list. */
  335 + BR_EXPORT static TemplateList fromGallery(const File &gallery); /*!< \brief Create a template list from a br::Gallery. */
335 336 BR_EXPORT static TemplateList relabel(const TemplateList &tl); /*!< \brief Ensure labels are in the range [0,numClasses-1]. */
  337 +
336 338 /*!
337 339 * \brief Returns the total number of bytes in all the templates.
338 340 */
... ... @@ -365,6 +367,11 @@ struct TemplateList : public QList&lt;Template&gt;
365 367 }
366 368  
367 369 /*!
  370 + * \brief Returns #br::Template::file for each template in the list.
  371 + */
  372 + FileList operator()() const { return files(); }
  373 +
  374 + /*!
368 375 * \brief Returns br::Template::label() for each template in the list.
369 376 */
370 377 template <typename T>
... ... @@ -859,6 +866,11 @@ class BR_EXPORT MatrixOutput : public Output
859 866 public:
860 867 cv::Mat data; /*!< \brief The similarity matrix. */
861 868  
  869 + /*!
  870 + * \brief Make a MatrixOutput from gallery and probe file lists.
  871 + */
  872 + static MatrixOutput *make(const FileList &targetFiles, const FileList &queryFiles);
  873 +
862 874 protected:
863 875 QString toString(int row, int column) const; /*!< \brief Converts the value requested similarity score to a string. */
864 876  
... ...
sdk/plugins/cascade.cpp
... ... @@ -37,7 +37,7 @@ public:
37 37 else if (model == "Eye") file += "haarcascades/haarcascade_eye_tree_eyeglasses.xml";
38 38 else if (model == "FrontalFace") file += "haarcascades/haarcascade_frontalface_alt2.xml";
39 39 else if (model == "ProfileFace") file += "haarcascades/haarcascade_profileface.xml";
40   - else qFatal("CascadeResourceMaker::CascadeResourceMaker invalid model.");
  40 + else qFatal("Invalid model.");
41 41 }
42 42  
43 43 private:
... ... @@ -45,7 +45,7 @@ private:
45 45 {
46 46 CascadeClassifier *cascade = new CascadeClassifier();
47 47 if (!cascade->load(file.toStdString()))
48   - qFatal("CascadeResourceMaker::make failed to load: %s", qPrintable(file));
  48 + qFatal("Failed to load: %s", qPrintable(file));
49 49 return cascade;
50 50 }
51 51 };
... ...
sdk/plugins/distance.cpp
... ... @@ -87,7 +87,7 @@ private:
87 87 }
88 88  
89 89 if (result != result)
90   - qFatal("Dist::compare NaN result.");
  90 + qFatal("NaN result.");
91 91  
92 92 return -log(result+1);
93 93 }
... ...
sdk/plugins/eigen3.cpp
... ... @@ -82,7 +82,7 @@ private:
82 82 void train(const TemplateList &trainingSet)
83 83 {
84 84 if (trainingSet.first().m().type() != CV_32FC1)
85   - qFatal("PCA::train requires single channel 32-bit floating point matrices.");
  85 + qFatal("Requires single channel 32-bit floating point matrices.");
86 86  
87 87 originalRows = trainingSet.first().m().rows;
88 88 int dimsIn = trainingSet.first().m().rows * trainingSet.first().m().cols;
... ... @@ -156,7 +156,7 @@ private:
156 156 }
157 157 } else {
158 158 if (keep + drop > allEVals.rows())
159   - qFatal("PCA::train insufficient samples, needed at least %d but only got %d.", (int)keep + drop, (int)allEVals.rows());
  159 + qFatal("Insufficient samples, needed at least %d but only got %d.", (int)keep + drop, (int)allEVals.rows());
160 160 }
161 161  
162 162 // Keep highest energy vectors
... ...
sdk/plugins/eyes.cpp
... ... @@ -71,10 +71,10 @@ public:
71 71  
72 72 // Open the eye locator model
73 73 file.setFileName(Globals->sdkPath + "/share/openbr/models/EyeLocatorASEF128x128.fel");
74   - bool success = file.open(QFile::ReadOnly); if (!success) qFatal("ASEFEyes::ASEFEyes failed to open %s for reading.", qPrintable(file.fileName()));
  74 + if (!file.open(QFile::ReadOnly)) qFatal("Failed to open %s for reading.", qPrintable(file.fileName()));
75 75  
76 76 // Check the first line
77   - line = file.readLine().simplified(); if (line != "CFEL") qFatal("ASEFEyes::ASEFEyes invalid header.");
  77 + if (file.readLine().simplified() != "CFEL") qFatal("Invalid header.");
78 78  
79 79 // Read past the comment and copyright.
80 80 file.readLine();
... ...
sdk/plugins/fill.cpp
... ... @@ -114,7 +114,7 @@ class BlendTransform : public UntrainableMetaTransform
114 114  
115 115 void project(const Template &src, Template &dst) const
116 116 {
117   - if (src.size() != 2) qFatal("Blend::project expected two source matrices.");
  117 + if (src.size() != 2) qFatal("Expected two source matrices.");
118 118 addWeighted(src[0], alpha, src[1], 1-alpha, 0, dst);
119 119 }
120 120 };
... ...
sdk/plugins/filter.cpp
... ... @@ -130,7 +130,7 @@ class CSDNTransform : public UntrainableTransform
130 130  
131 131 void project(const Template &src, Template &dst) const
132 132 {
133   - if (src.m().channels() != 1) qFatal("ContrastEq::project expected single channel source matrix.");
  133 + if (src.m().channels() != 1) qFatal("Expected single channel source matrix.");
134 134  
135 135 const int nRows = src.m().rows;
136 136 const int nCols = src.m().cols;
... ... @@ -180,7 +180,7 @@ class ContrastEqTransform : public UntrainableTransform
180 180  
181 181 void project(const Template &src, Template &dst) const
182 182 {
183   - if (src.m().channels() != 1) qFatal("ContrastEq::project expected single channel source matrix.");
  183 + if (src.m().channels() != 1) qFatal("Expected single channel source matrix.");
184 184  
185 185 // Stage 1
186 186 Mat stage1;
... ...
sdk/plugins/format.cpp
... ... @@ -112,7 +112,7 @@ class binFormat : public Format
112 112 {
113 113 Mat m;
114 114 t.m().convertTo(m, CV_32F);
115   - if (m.channels() != 1) qFatal("binFormat::write only supports single channel matrices.");
  115 + if (m.channels() != 1) qFatal("Only supports single channel matrices.");
116 116  
117 117 QByteArray data;
118 118 QDataStream stream(&data, QFile::WriteOnly);
... ... @@ -168,8 +168,8 @@ class csvFormat : public Format
168 168 void write(const Template &t) const
169 169 {
170 170 const Mat &m = t.m();
171   - if (t.size() != 1) qFatal("csvFormat::write only supports single matrix templates.");
172   - if (m.channels() != 1) qFatal("csvFormat::write only supports single channel matrices.");
  171 + if (t.size() != 1) qFatal("Only supports single matrix templates.");
  172 + if (m.channels() != 1) qFatal("Only supports single channel matrices.");
173 173  
174 174 QStringList lines; lines.reserve(m.rows);
175 175 for (int r=0; r<m.rows; r++) {
... ... @@ -337,7 +337,7 @@ class matFormat : public Format
337 337 int skipBytes = (bytes < 4) ? (4 - bytes) : (8 - bytes%8)%8;
338 338 if (skipBytes != 0) stream.skipRawData(skipBytes);
339 339  
340   - if (error) qFatal("matFormat::Element Unexpected end of file.");
  340 + if (error) qFatal("Unexpected end of file.");
341 341 }
342 342  
343 343 void print() const
... ... @@ -356,7 +356,7 @@ class matFormat : public Format
356 356 QByteArray header(128, 0);
357 357 f.readRawData(header.data(), 128);
358 358 if (!header.startsWith("MATLAB 5.0 MAT-file"))
359   - qFatal("matFormat::read Invalid MAT header.");
  359 + qFatal("Invalid MAT header.");
360 360 }
361 361  
362 362 Template t(file);
... ... @@ -426,7 +426,7 @@ class matFormat : public Format
426 426  
427 427 for (int i=0; i<t.size(); i++) {
428 428 const Mat &m = t[i];
429   - if (m.channels() != 1) qFatal("matFormat::write only supports single channel matrices.");
  429 + if (m.channels() != 1) qFatal("Only supports single channel matrices.");
430 430  
431 431 QByteArray subdata;
432 432 QDataStream substream(&subdata, QFile::WriteOnly);
... ... @@ -443,7 +443,7 @@ class matFormat : public Format
443 443 case CV_16UC1: arrayClass = 10; break;
444 444 case CV_16SC1: arrayClass = 11; break;
445 445 case CV_32SC1: arrayClass = 12; break;
446   - default: qFatal("matFormat::write unsupported matrix class.");
  446 + default: qFatal("Unsupported matrix class.");
447 447 }
448 448 substream.writeRawData((const char*)&type, 4);
449 449 substream.writeRawData((const char*)&bytes, 4);
... ... @@ -480,7 +480,7 @@ class matFormat : public Format
480 480 case CV_32SC1: type = 5; break;
481 481 case CV_32FC1: type = 7; break;
482 482 case CV_64FC1: type = 9; break;
483   - default: qFatal("matFormat::write unsupported matrix type.");
  483 + default: qFatal("Unsupported matrix type.");
484 484 }
485 485 quint32 bytes = m.elemSize() * m.rows * m.cols;
486 486 QByteArray buffer((8 - bytes%8)%8, 0);
... ... @@ -531,7 +531,7 @@ class webcamFormat : public Format
531 531 void write(const Template &t) const
532 532 {
533 533 (void) t;
534   - qFatal("webcamFormat::write not supported.");
  534 + qFatal("Not supported.");
535 535 }
536 536 };
537 537  
... ... @@ -552,8 +552,8 @@ class xmlFormat : public Format
552 552 {
553 553 QDomDocument doc(file);
554 554 QFile f(file);
555   - if (!f.open(QIODevice::ReadOnly)) qFatal("xmlFormat::read unable to open %s for reading.", qPrintable(file.flat()));
556   - if (!doc.setContent(&f)) qFatal("xmlFormat::read unable to parse %s.", qPrintable(file.flat()));
  555 + if (!f.open(QIODevice::ReadOnly)) qFatal("Unable to open %s for reading.", qPrintable(file.flat()));
  556 + if (!doc.setContent(&f)) qFatal("Unable to parse %s.", qPrintable(file.flat()));
557 557 f.close();
558 558  
559 559 Template t;
... ... @@ -599,7 +599,7 @@ class xmlFormat : public Format
599 599 void write(const Template &t) const
600 600 {
601 601 (void) t;
602   - qFatal("xmlFormat::write not supported.");
  602 + qFatal("Not supported.");
603 603 }
604 604 };
605 605  
... ...
sdk/plugins/gallery.cpp
... ... @@ -80,7 +80,7 @@ BR_REGISTER(Gallery, galGallery)
80 80  
81 81 /*!
82 82 * \ingroup galleries
83   - * \brief Reads and writes templates to folders of images.
  83 + * \brief Reads/writes templates to/from folders.
84 84 * \author Josh Klontz \cite jklontz
85 85 */
86 86 class EmptyGallery : public Gallery
... ... @@ -120,9 +120,14 @@ class EmptyGallery : public Gallery
120 120 // Enrolling a null file is used as an idiom to initialize an algorithm
121 121 if (file.name.isEmpty()) return;
122 122  
123   - QMutexLocker diskLocker(&diskLock);
124   - if (t.isNull()) QFile::copy((t.file.exists() ? QString() : Globals->path+"/") + t.file.name, file.name + "/" + t.file.fileName());
125   - else OpenCVUtils::saveImage(t, file.name + "/" + t.file.baseName() + ".png");
  123 + const QString destination = file.name + "/" + t.file.fileName();
  124 + QMutexLocker diskLocker(&diskLock); // Windows prefers to crash when writing to disk in parallel
  125 + if (t.isNull()) {
  126 + QFile::copy(t.file.resolved(), destination);
  127 + } else {
  128 + QScopedPointer<Format> format(Factory<Format>::make(destination));
  129 + format->write(t);
  130 + }
126 131 }
127 132 };
128 133  
... ... @@ -286,12 +291,12 @@ class memGallery : public Gallery
286 291 size_t offset = 0;
287 292 for (int i=0; i<templates.size(); i++) {
288 293 Template &t = templates[i];
289   - if (t.size() > 1) qFatal("memGallery::align can't handle multi-matrix template %s.", qPrintable(t.file.flat()));
  294 + if (t.size() > 1) qFatal("Can't handle multi-matrix template %s.", qPrintable(t.file.flat()));
290 295  
291 296 cv::Mat &m = t;
292 297 if (m.data) {
293 298 const size_t size = m.total() * m.elemSize();
294   - if (!m.isContinuous()) qFatal("memGallery::align requires continuous matrix data of size %d for %s.", (int)size, qPrintable(t.file.flat()));
  299 + if (!m.isContinuous()) qFatal("Requires continuous matrix data of size %d for %s.", (int)size, qPrintable(t.file.flat()));
295 300 memcpy(&(alignedData.data()[offset]), m.ptr(), size);
296 301 m = cv::Mat(m.rows, m.cols, m.type(), &(alignedData.data()[offset]));
297 302 offset += size;
... ... @@ -591,7 +596,7 @@ class dbGallery : public Gallery
591 596 void write(const Template &t)
592 597 {
593 598 (void) t;
594   - qFatal("Writing not supported.");
  599 + qFatal("Not supported.");
595 600 }
596 601 };
597 602  
... ... @@ -644,7 +649,7 @@ class googleGallery : public Gallery
644 649 void write(const Template &t)
645 650 {
646 651 (void) t;
647   - qFatal("Writing to a txtGallery not supported.");
  652 + qFatal("Not supported.");
648 653 }
649 654 };
650 655  
... ...
sdk/plugins/keypoint.cpp
... ... @@ -42,7 +42,7 @@ class KeyPointDetectorTransform : public UntrainableTransform
42 42 {
43 43 featureDetector = FeatureDetector::create(detector.toStdString());
44 44 if (featureDetector.empty())
45   - qFatal("KeyPointDetector::init failed to create KeyPointDetector: %s", qPrintable(detector));
  45 + qFatal("Failed to create KeyPointDetector: %s", qPrintable(detector));
46 46 }
47 47  
48 48 void project(const Template &src, Template &dst) const
... ... @@ -85,7 +85,7 @@ class KeyPointDescriptorTransform : public UntrainableTransform
85 85 {
86 86 descriptorExtractor = DescriptorExtractor::create(descriptor.toStdString());
87 87 if (descriptorExtractor.empty())
88   - qFatal("KeyPointDescriptor::make failed to create DescriptorExtractor: %s", qPrintable(descriptor));
  88 + qFatal("Failed to create DescriptorExtractor: %s", qPrintable(descriptor));
89 89 }
90 90  
91 91 void project(const Template &src, Template &dst) const
... ... @@ -123,7 +123,7 @@ class KeyPointMatcherTransform : public Distance
123 123 {
124 124 descriptorMatcher = DescriptorMatcher::create(matcher.toStdString());
125 125 if (descriptorMatcher.empty())
126   - qFatal("KeyPointMatcher::make failed to create DescriptorMatcher: %s", qPrintable(matcher));
  126 + qFatal("Failed to create DescriptorMatcher: %s", qPrintable(matcher));
127 127 }
128 128  
129 129 float compare(const Template &a, const Template &b) const
... ...
sdk/plugins/lbp.cpp
... ... @@ -171,7 +171,7 @@ class ColoredU2Transform : public UntrainableTransform
171 171 }
172 172  
173 173 if (src.m().type() != CV_8UC1)
174   - qFatal("ColoredU2::project expected 8UC1 source type.");
  174 + qFatal("Expected 8UC1 source type.");
175 175  
176 176 Mat hue, saturation, value;
177 177 LUT(src, hueLUT, hue);
... ...
sdk/plugins/mask.cpp
... ... @@ -59,7 +59,7 @@ class GradientMaskTransform : public UntrainableTransform
59 59 void project(const Template &src, Template &dst) const
60 60 {
61 61 const Mat &m = src.m();
62   - if (m.type() != CV_8UC1) qFatal("GradientMask operates on 8UC1 matrices.");
  62 + if (m.type() != CV_8UC1) qFatal("Requires 8UC1 matrices.");
63 63 Mat n = Mat(m.rows, m.cols, CV_8UC1);
64 64 n.setTo(255);
65 65 for (int i=0; i<m.rows; i++) {
... ...
sdk/plugins/meta.cpp
... ... @@ -39,8 +39,8 @@ static TemplateList Simplified(const TemplateList &amp;templates)
39 39 const bool fte = t.file.getBool("FTE");
40 40 QList<QPointF> landmarks = t.file.landmarks();
41 41 QList<QRectF> ROIs = t.file.ROIs();
42   - if (landmarks.size() % t.size() != 0) qFatal("TemplateList::simplified uneven landmark count.");
43   - if (ROIs.size() % t.size() != 0) qFatal("TemplateList::simplified uneven ROI count.");
  42 + if (landmarks.size() % t.size() != 0) qFatal("Uneven landmark count.");
  43 + if (ROIs.size() % t.size() != 0) qFatal("Uneven ROI count.");
44 44 const int landmarkStep = landmarks.size() / t.size();
45 45 const int ROIStep = ROIs.size() / t.size();
46 46  
... ... @@ -281,7 +281,7 @@ class ForkTransform : public MetaTransform
281 281 foreach (const Transform *f, transforms) {
282 282 TemplateList m;
283 283 f->project(src, m);
284   - if (m.size() != dst.size()) qFatal("Fork::project templateList is of an unexpected size.");
  284 + if (m.size() != dst.size()) qFatal("TemplateList is of an unexpected size.");
285 285 for (int i=0; i<src.size(); i++) dst[i].append(m[i]);
286 286 }
287 287 } else {
... ... @@ -313,7 +313,8 @@ public:
313 313  
314 314 // Write to cache
315 315 QFile file("Cache");
316   - bool success = file.open(QFile::WriteOnly); if (!success) qFatal("Cache::Cache unable to open %s for writing.", qPrintable(file.fileName()));
  316 + if (!file.open(QFile::WriteOnly))
  317 + qFatal("Unable to open %s for writing.", qPrintable(file.fileName()));
317 318 QDataStream stream(&file);
318 319 stream << cache;
319 320 file.close();
... ... @@ -327,7 +328,8 @@ private:
327 328 // Read from cache
328 329 QFile file("Cache");
329 330 if (file.exists()) {
330   - bool success = file.open(QFile::ReadOnly); if (!success) qFatal("Cache::make unable to open %s for reading.", qPrintable(file.fileName()));
  331 + if (!file.open(QFile::ReadOnly))
  332 + qFatal("Unable to open %s for reading.", qPrintable(file.fileName()));
331 333 QDataStream stream(&file);
332 334 stream >> cache;
333 335 file.close();
... ... @@ -458,7 +460,8 @@ class FTETransform : public Transform
458 460  
459 461 QList<float> vals;
460 462 foreach (const Template &t, projectedData) {
461   - if (!t.file.contains(transform->objectName())) qFatal("FTE::train matrix metadata missing key %s.", qPrintable(transform->objectName()));
  463 + if (!t.file.contains(transform->objectName()))
  464 + qFatal("Matrix metadata missing key %s.", qPrintable(transform->objectName()));
462 465 vals.append(t.file.getFloat(transform->objectName()));
463 466 }
464 467 float q1, q3;
... ...
sdk/plugins/normalize.cpp
... ... @@ -100,7 +100,7 @@ private:
100 100 if (method == Mean) mean(m.col(i), &A, &B);
101 101 else if (method == Median) median(m.col(i), &A, &B);
102 102 else if (method == Range) range(m.col(i), &A, &B);
103   - else qFatal("Center::train invalid method");
  103 + else qFatal("Invalid method.");
104 104 ca->at<double>(0, i) = A;
105 105 cb->at<double>(0, i) = B;
106 106 }
... ...
sdk/plugins/pixel.cpp
... ... @@ -54,7 +54,6 @@ class PerPixelClassifierTransform : public MetaTransform
54 54  
55 55 void rotate(Template &src, Template &dst) const
56 56 {
57   - //if (src.m().cols%9 != 0) qFatal("Rotation invariance can only be used after Neighbors");
58 57 int images = (src.m().cols)/9;
59 58 dst = src;
60 59 for (int i = 0; i < images; i++){
... ...
sdk/plugins/pp5.cpp
... ... @@ -283,7 +283,7 @@ class PP5Compare : public Distance
283 283 {
284 284 (void) target;
285 285 (void) query;
286   - qFatal("PP5Compare::compare (single templates) should never be called!");
  286 + qFatal("Compare single templates should never be called!");
287 287 return 0;
288 288 }
289 289  
... ...
sdk/plugins/quality.cpp
... ... @@ -158,15 +158,15 @@ class MatchProbabilityDistance : public Distance
158 158 distance->train(src);
159 159  
160 160 const QList<int> labels = src.labels<int>();
161   - QScopedPointer<MatrixOutput> memoryOutput(dynamic_cast<MatrixOutput*>(Output::make(".Matrix", FileList(src.size()), FileList(src.size()))));
162   - distance->compare(src, src, memoryOutput.data());
  161 + QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(src.size()), FileList(src.size())));
  162 + distance->compare(src, src, matrixOutput.data());
163 163  
164 164 QList<float> genuineScores, impostorScores;
165 165 genuineScores.reserve(labels.size());
166 166 impostorScores.reserve(labels.size()*labels.size());
167 167 for (int i=0; i<src.size(); i++) {
168 168 for (int j=0; j<i; j++) {
169   - const float score = memoryOutput.data()->data.at<float>(i, j);
  169 + const float score = matrixOutput.data()->data.at<float>(i, j);
170 170 if (score == -std::numeric_limits<float>::max()) continue;
171 171 if (labels[i] == labels[j]) genuineScores.append(score);
172 172 else impostorScores.append(score);
... ... @@ -217,8 +217,8 @@ class UnitDistance : public Distance
217 217 {
218 218 const TemplateList samples = templates.mid(0, 2000);
219 219 const QList<float> sampleLabels = samples.labels<float>();
220   - QScopedPointer<MatrixOutput> memoryOutput(dynamic_cast<MatrixOutput*>(Output::make(".Matrix", FileList(samples.size()), FileList(samples.size()))));
221   - Distance::compare(samples, samples, memoryOutput.data());
  220 + QScopedPointer<MatrixOutput> matrixOutput(MatrixOutput::make(FileList(samples.size()), FileList(samples.size())));
  221 + Distance::compare(samples, samples, matrixOutput.data());
222 222  
223 223 double genuineAccumulator, impostorAccumulator;
224 224 int genuineCount, impostorCount;
... ... @@ -226,7 +226,7 @@ class UnitDistance : public Distance
226 226  
227 227 for (int i=0; i<samples.size(); i++) {
228 228 for (int j=0; j<i; j++) {
229   - const float val = memoryOutput.data()->data.at<float>(i, j);
  229 + const float val = matrixOutput.data()->data.at<float>(i, j);
230 230 if (sampleLabels[i] == sampleLabels[j]) {
231 231 genuineAccumulator += val;
232 232 genuineCount++;
... ...
sdk/plugins/quantize.cpp
... ... @@ -95,7 +95,7 @@ class PackTransform : public UntrainableTransform
95 95 {
96 96 const Mat &m = src;
97 97 if ((m.cols % 2 != 0) || (m.type() != CV_8UC1))
98   - qFatal("Pack::project invalid template format.");
  98 + qFatal("Invalid template format.");
99 99  
100 100 Mat n(m.rows, m.cols/2, CV_8UC1);
101 101 for (int i=0; i<m.rows; i++)
... ...
sdk/plugins/reduce.cpp
... ... @@ -32,7 +32,7 @@ class SubtractTransform : public UntrainableMetaTransform
32 32  
33 33 void project(const Template &src, Template &dst) const
34 34 {
35   - if (src.size() != 2) qFatal("Subtract::project expected exactly two source images, got %d.", src.size());
  35 + if (src.size() != 2) qFatal("Expected exactly two source images, got %d.", src.size());
36 36 dst.file = src.file;
37 37 subtract(src[0], src[1], dst);
38 38 }
... ... @@ -51,7 +51,7 @@ class AbsDiffTransform : public UntrainableMetaTransform
51 51  
52 52 void project(const Template &src, Template &dst) const
53 53 {
54   - if (src.size() != 2) qFatal("AbsDiff::project expected exactly two source images, got %d.", src.size());
  54 + if (src.size() != 2) qFatal("Expected exactly two source images, got %d.", src.size());
55 55 dst.file = src.file;
56 56 absdiff(src[0], src[1], dst);
57 57 }
... ...
sdk/plugins/regions.cpp
... ... @@ -89,7 +89,7 @@ class CatTransform : public UntrainableMetaTransform
89 89 dst.file = src.file;
90 90  
91 91 if (src.size() % partitions != 0)
92   - qFatal("Cat %d partitions does not evenly divide %d matrices.", partitions, src.size());
  92 + qFatal("%d partitions does not evenly divide %d matrices.", partitions, src.size());
93 93 QVector<int> sizes(partitions, 0);
94 94 for (int i=0; i<src.size(); i++)
95 95 sizes[i%partitions] += src[i].total() * src[i].channels();
... ...
sdk/plugins/svm.cpp
... ... @@ -86,7 +86,7 @@ private:
86 86 }
87 87  
88 88 if (data.type() != CV_32FC1)
89   - qFatal("SVM::train expected single channel floating point training data.");
  89 + qFatal("Expected single channel floating point training data.");
90 90  
91 91 CvSVMParams params;
92 92 params.kernel_type = kernel;
... ...
sdk/plugins/synthetic.cpp
... ... @@ -71,7 +71,7 @@ class OrigLinearRegressionTransform : public UntrainableMetaTransform
71 71  
72 72 void project(const Template &src, Template &dst) const
73 73 {
74   - if (src.size() != 3) qFatal("OrigLinearRegression::project expected exactly three source images, got %d.", src.size());
  74 + if (src.size() != 3) qFatal("Expected exactly three source images, got %d.", src.size());
75 75 Mat m1; src[0].convertTo(m1, CV_32F); assert(m1.isContinuous() && (m1.channels() == 1));
76 76 Mat m2; src[1].convertTo(m2, CV_32F); assert(m2.isContinuous() && (m2.channels() == 1));
77 77 Mat m3; src[2].convertTo(m3, CV_32F); assert(m3.isContinuous() && (m3.channels() == 1));
... ...
sdk/plugins/wavelet.cpp
... ... @@ -109,7 +109,7 @@ private:
109 109 else if (component == Imaginary) dst = imaginary;
110 110 else if (component == Magnitude) dst = magnitude;
111 111 else if (component == Phase) dst = phase;
112   - else qFatal("Gabor::project invalid component.");
  112 + else qFatal("Invalid component.");
113 113 }
114 114 };
115 115  
... ... @@ -183,7 +183,7 @@ class GaborJetTransform : public UntrainableTransform
183 183 else if (component == GaborTransform::Imaginary) dst = imaginary;
184 184 else if (component == GaborTransform::Magnitude) dst = magnitude;
185 185 else if (component == GaborTransform::Phase) dst = phase;
186   - else qFatal("GaborJet::response invalid component.");
  186 + else qFatal("Invalid component.");
187 187 return dst;
188 188 }
189 189  
... ...
sdk/plugins/youtube.cpp 0 → 100644
  1 +#include <openbr_plugin.h>
  2 +
  3 +namespace br
  4 +{
  5 +
  6 +/*!
  7 + * \ingroup transforms
  8 + * \brief Implements the YouTubesFaceDB \cite wolf11 experimental protocol.
  9 + * \author Josh Klontz \cite jklontz
  10 + */
  11 +class YouTubeFacesDBTransform : public UntrainableMetaTransform
  12 +{
  13 + Q_OBJECT
  14 + Q_PROPERTY(QString algorithm READ get_algorithm WRITE set_algorithm RESET reset_algorithm STORED false)
  15 + BR_PROPERTY(QString, algorithm, "")
  16 +
  17 + QSharedPointer<Transform> transform;
  18 + QSharedPointer<Distance> distance;
  19 +
  20 + void init()
  21 + {
  22 + transform = Transform::fromAlgorithm(algorithm);
  23 + distance = Distance::fromAlgorithm(algorithm);
  24 + }
  25 +
  26 + void project(const Template &src, Template &dst) const
  27 + {
  28 + dst = src;
  29 +
  30 + // First input is the header in 'splits.txt'
  31 + if (src.file.getInt("Index") == 0) return;
  32 +
  33 + const QStringList words = src.file.name.split(", ");
  34 + dst.file.name = words[0] + "_" + words[1] + "_" + words[4] + ".mtx";
  35 +
  36 + TemplateList queryTemplates = TemplateList::fromGallery(File(words[2]).resolved());
  37 + queryTemplates >> *transform;
  38 +
  39 + TemplateList targetTemplates = TemplateList::fromGallery(File(words[3]).resolved());
  40 + targetTemplates >> *transform;
  41 +
  42 + QScopedPointer<MatrixOutput> memoryOutput(MatrixOutput::make(targetTemplates.files(), queryTemplates.files()));
  43 + distance->compare(targetTemplates, queryTemplates, memoryOutput.data());
  44 +
  45 + dst.clear();
  46 + dst.m() = memoryOutput.data()->data;
  47 + }
  48 +};
  49 +
  50 +BR_REGISTER(Transform, YouTubeFacesDBTransform)
  51 +
  52 +} // namespace br
  53 +
  54 +#include "youtube.moc"
... ...
share/openbr/openbr.bib
... ... @@ -162,6 +162,14 @@
162 162 Title = {Spectral Hashing},
163 163 Year = {2008}}
164 164  
  165 +@inproceedings{wolf11,
  166 + author={Wolf, L. and Hassner, T. and Maoz, I.},
  167 + booktitle={Computer Vision and Pattern Recognition (CVPR), 2011 IEEE Conference on},
  168 + title={Face recognition in unconstrained videos with matched background similarity},
  169 + year={2011},
  170 + month={june},
  171 + pages={529-534}}
  172 +
165 173 @mastersthesis{zauner10,
166 174 Author = {Zauner, C.},
167 175 School = {Upper Austria University of Applied Sciences, Hagenberg Campus},
... ...