Commit bee4a6fe0b4c0f60b9ceb9d8560e706b307e0fe0

Authored by Scott Klum
1 parent a31c2022

Updates

openbr/core/bee.cpp
@@ -112,7 +112,7 @@ void BEE::writeSigset(const QString &sigset, const br::FileList &files, bool ign @@ -112,7 +112,7 @@ void BEE::writeSigset(const QString &sigset, const br::FileList &files, bool ign
112 metadata.append("Rects=\"["+landmarks.join(",")+"]\""); 112 metadata.append("Rects=\"["+landmarks.join(",")+"]\"");
113 } 113 }
114 } 114 }
115 - lines.append("\t<biometric-signature name=\"" + file.get<QString>("Label",file.fileName()) +"\">"); 115 + lines.append("\t<biometric-signature name=\"" + file.baseName() +"\">");
116 lines.append("\t\t<presentation file-name=\"" + file.name + "\" " + metadata.join(" ") + "/>"); 116 lines.append("\t\t<presentation file-name=\"" + file.name + "\" " + metadata.join(" ") + "/>");
117 lines.append("\t</biometric-signature>"); 117 lines.append("\t</biometric-signature>");
118 } 118 }
openbr/core/eval.cpp
@@ -167,7 +167,7 @@ float Evaluate(const Mat &amp;simmat, const Mat &amp;mask, const QString &amp;csv) @@ -167,7 +167,7 @@ float Evaluate(const Mat &amp;simmat, const Mat &amp;mask, const QString &amp;csv)
167 if ((falsePositives > previousFalsePositives) && 167 if ((falsePositives > previousFalsePositives) &&
168 (truePositives > previousTruePositives)) { 168 (truePositives > previousTruePositives)) {
169 // Restrict the extreme ends of the curve 169 // Restrict the extreme ends of the curve
170 - if ((truePositives >= 10) && (falsePositives < impostorCount/2)) 170 + //if ((truePositives >= 10) && (falsePositives < impostorCount/2))
171 operatingPoints.append(OperatingPoint(thresh, float(falsePositives)/impostorCount, float(truePositives)/genuineCount)); 171 operatingPoints.append(OperatingPoint(thresh, float(falsePositives)/impostorCount, float(truePositives)/genuineCount));
172 previousFalsePositives = falsePositives; 172 previousFalsePositives = falsePositives;
173 previousTruePositives = truePositives; 173 previousTruePositives = truePositives;
openbr/core/plot.cpp
@@ -236,7 +236,7 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show) @@ -236,7 +236,7 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show)
236 QString(", xlab=\"False Accept Rate\", ylab=\"False Reject Rate\") + geom_abline(alpha=0.5, colour=\"grey\", linetype=\"dashed\") + theme_minimal()") + 236 QString(", xlab=\"False Accept Rate\", ylab=\"False Reject Rate\") + geom_abline(alpha=0.5, colour=\"grey\", linetype=\"dashed\") + theme_minimal()") +
237 (p.major.size > 1 ? getScale("colour", p.major.header, p.major.size) : QString()) + 237 (p.major.size > 1 ? getScale("colour", p.major.header, p.major.size) : QString()) +
238 (p.minor.size > 1 ? QString(" + scale_linetype_discrete(\"%1\")").arg(p.minor.header) : QString()) + 238 (p.minor.size > 1 ? QString(" + scale_linetype_discrete(\"%1\")").arg(p.minor.header) : QString()) +
239 - QString(" + scale_x_log10(labels=percent, limits=c(min(DET$X),1)) + scale_y_log10(labels=percent) + annotation_logticks()\n\n"))); 239 + QString(" + scale_x_log10(labels=percent, limits=c(min(DET$X),1)) + scale_y_continuous(labels=percent)\n\n")));
240 240
241 p.file.write(qPrintable(QString("qplot(X, data=SD, geom=\"histogram\", fill=Y, position=\"identity\", alpha=I(1/2)") + 241 p.file.write(qPrintable(QString("qplot(X, data=SD, geom=\"histogram\", fill=Y, position=\"identity\", alpha=I(1/2)") +
242 QString(", xlab=\"Score%1\"").arg((p.flip ? p.major.size : p.minor.size) > 1 ? " / " + (p.flip ? p.major.header : p.minor.header) : QString()) + 242 QString(", xlab=\"Score%1\"").arg((p.flip ? p.major.size : p.minor.size) > 1 ? " / " + (p.flip ? p.major.header : p.minor.header) : QString()) +
openbr/openbr_plugin.cpp
@@ -441,10 +441,10 @@ TemplateList TemplateList::fromGallery(const br::File &amp;gallery) @@ -441,10 +441,10 @@ TemplateList TemplateList::fromGallery(const br::File &amp;gallery)
441 // of target images to every partition 441 // of target images to every partition
442 newTemplates[i].file.set("Partition", -1); 442 newTemplates[i].file.set("Partition", -1);
443 } else { 443 } else {
444 - // Direct use of "Label" is not general -cao  
445 - const QByteArray md5 = QCryptographicHash::hash(newTemplates[i].file.get<QString>("Label").toLatin1(), QCryptographicHash::Md5);  
446 - // Select the right 8 hex characters so that it can be represented as a 64 bit integer without overflow  
447 - newTemplates[i].file.set("Partition", md5.toHex().right(8).toULongLong(0, 16) % crossValidate); 444 + // Direct use of "Label" is not general -cao
  445 + const QByteArray md5 = QCryptographicHash::hash(newTemplates[i].file.get<QString>("Label").toLatin1(), QCryptographicHash::Md5);
  446 + // Select the right 8 hex characters so that it can be represented as a 64 bit integer without overflow
  447 + newTemplates[i].file.set("Partition", md5.toHex().right(8).toULongLong(0, 16) % crossValidate);
448 } 448 }
449 } 449 }
450 } 450 }
openbr/plugins/crop.cpp
@@ -60,8 +60,13 @@ class ROITransform : public UntrainableTransform @@ -60,8 +60,13 @@ class ROITransform : public UntrainableTransform
60 60
61 void project(const Template &src, Template &dst) const 61 void project(const Template &src, Template &dst) const
62 { 62 {
63 - foreach (const QRectF &rect, src.file.rects())  
64 - dst += src.m()(OpenCVUtils::toRect(rect)); 63 + if (src.file.rects().empty()) {
  64 + dst = src;
  65 + qWarning("No rects present in file.");
  66 + }
  67 + else
  68 + foreach (const QRectF &rect, src.file.rects())
  69 + dst += src.m()(OpenCVUtils::toRect(rect));
65 } 70 }
66 }; 71 };
67 72
openbr/plugins/distance.cpp
@@ -310,7 +310,7 @@ class OnlineDistance : public Distance @@ -310,7 +310,7 @@ class OnlineDistance : public Distance
310 Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false) 310 Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false)
311 Q_PROPERTY(float alpha READ get_alpha WRITE set_alpha RESET reset_alpha STORED false) 311 Q_PROPERTY(float alpha READ get_alpha WRITE set_alpha RESET reset_alpha STORED false)
312 BR_PROPERTY(br::Distance*, distance, NULL) 312 BR_PROPERTY(br::Distance*, distance, NULL)
313 - BR_PROPERTY(float, alpha, 0.1f); 313 + BR_PROPERTY(float, alpha, 0.1f)
314 314
315 mutable QHash<QString,float> scoreHash; 315 mutable QHash<QString,float> scoreHash;
316 mutable QMutex mutex; 316 mutable QMutex mutex;
openbr/plugins/draw.cpp
@@ -46,11 +46,11 @@ class DrawTransform : public UntrainableTransform @@ -46,11 +46,11 @@ class DrawTransform : public UntrainableTransform
46 void project(const Template &src, Template &dst) const 46 void project(const Template &src, Template &dst) const
47 { 47 {
48 const Scalar color(0,255,0); 48 const Scalar color(0,255,0);
49 - const Scalar verboseColor(255, 255, 0); 49 + const Scalar verboseColor(0, 0, 0);
50 dst.m() = inPlace ? src.m() : src.m().clone(); 50 dst.m() = inPlace ? src.m() : src.m().clone();
51 51
52 if (points) { 52 if (points) {
53 - const QList<Point2f> pointsList = OpenCVUtils::toPoints(src.file.namedPoints() + src.file.points()); 53 + const QList<Point2f> pointsList = OpenCVUtils::toPoints(src.file.points());
54 for (int i=0; i<pointsList.size(); i++) { 54 for (int i=0; i<pointsList.size(); i++) {
55 const Point2f &point = pointsList[i]; 55 const Point2f &point = pointsList[i];
56 circle(dst, point, 3, color, -1); 56 circle(dst, point, 3, color, -1);
openbr/plugins/filter.cpp
@@ -139,10 +139,8 @@ class CSDNTransform : public UntrainableTransform @@ -139,10 +139,8 @@ class CSDNTransform : public UntrainableTransform
139 139
140 const int surround = s/2; 140 const int surround = s/2;
141 141
142 - for ( int i = 0; i < nRows; i++ )  
143 - {  
144 - for ( int j = 0; j < nCols; j++ )  
145 - { 142 + for ( int i = 0; i < nRows; i++ ) {
  143 + for ( int j = 0; j < nCols; j++ ) {
146 int width = min( j+surround, nCols ) - max( 0, j-surround ); 144 int width = min( j+surround, nCols ) - max( 0, j-surround );
147 int height = min( i+surround, nRows ) - max( 0, i-surround ); 145 int height = min( i+surround, nRows ) - max( 0, i-surround );
148 146
openbr/plugins/gallery.cpp
@@ -119,7 +119,8 @@ class galGallery : public Gallery @@ -119,7 +119,8 @@ class galGallery : public Gallery
119 { 119 {
120 if (t.isEmpty() && t.file.isNull()) 120 if (t.isEmpty() && t.file.isNull())
121 return; 121 return;
122 - stream << t; 122 + if (t.file.baseName() != "204765279_PCSOdata")
  123 + stream << t;
123 } 124 }
124 }; 125 };
125 126
@@ -185,7 +186,7 @@ class EmptyGallery : public Gallery @@ -185,7 +186,7 @@ class EmptyGallery : public Gallery
185 if (file.name.isEmpty()) return; 186 if (file.name.isEmpty()) return;
186 187
187 const QString newFormat = file.get<QString>("newFormat",QString()); 188 const QString newFormat = file.get<QString>("newFormat",QString());
188 - QString destination = file.name + "/" + (file.getBool("preservePath") ? t.file.path()+"/" : QString()); 189 + QString destination = file.name + "/fold_" + QString::number(t.file.get<int>("Partition")) + "/target/" + (file.getBool("preservePath") ? t.file.path()+"/" : QString());
189 destination += (newFormat.isEmpty() ? t.file.fileName() : t.file.baseName()+newFormat); 190 destination += (newFormat.isEmpty() ? t.file.fileName() : t.file.baseName()+newFormat);
190 191
191 QMutexLocker diskLocker(&diskLock); // Windows prefers to crash when writing to disk in parallel 192 QMutexLocker diskLocker(&diskLock); // Windows prefers to crash when writing to disk in parallel
openbr/plugins/misc.cpp
@@ -382,50 +382,38 @@ BR_REGISTER(Transform, RegexPropertyTransform) @@ -382,50 +382,38 @@ BR_REGISTER(Transform, RegexPropertyTransform)
382 382
383 /*! 383 /*!
384 * \ingroup transforms 384 * \ingroup transforms
385 - * \brief Remove templates with the specified file extension or metadata value.  
386 - * \author Josh Klontz \cite jklontz 385 + * \brief Calculate metadata statistics
  386 + * \author Scott Klum \cite sklum
387 */ 387 */
388 -class RemoveTemplatesTransform : public UntrainableMetaTransform 388 +class MetadataStatisticsTransform : public Transform
389 { 389 {
390 Q_OBJECT 390 Q_OBJECT
391 - Q_PROPERTY(QString regexp READ get_regexp WRITE set_regexp RESET reset_regexp STORED false)  
392 - Q_PROPERTY(QString key READ get_key WRITE set_key RESET reset_key STORED false)  
393 - BR_PROPERTY(QString, regexp, "")  
394 - BR_PROPERTY(QString, key, "") 391 + Q_PROPERTY(QStringList keys READ get_keys WRITE set_keys RESET reset_keys STORED false)
  392 + BR_PROPERTY(QStringList, keys, QStringList())
395 393
396 - void project(const Template &src, Template &dst) const 394 + void train(const TemplateList &data)
397 { 395 {
398 - const QRegularExpression re(regexp);  
399 - const QRegularExpressionMatch match = re.match(key.isEmpty() ? src.file.suffix() : src.file.get<QString>(key));  
400 - if (match.hasMatch()) dst = Template();  
401 - else dst = src;  
402 - }  
403 -}; 396 + QHash<QString,int> statHash;
404 397
405 -BR_REGISTER(Transform, RemoveTemplatesTransform) 398 + foreach (const Template &t, data) {
  399 + foreach (const QString &key, keys) {
  400 + QString value = t.file.get<QString>(key, QString());
406 401
407 -/*!  
408 - * \ingroup transforms  
409 - * \brief Remove template metadata with the specified key(s).  
410 - * \author Josh Klontz \cite jklontz  
411 - */  
412 -class RemoveMetadataTransform : public UntrainableMetaTransform  
413 -{  
414 - Q_OBJECT  
415 - Q_PROPERTY(QString regexp READ get_regexp WRITE set_regexp RESET reset_regexp STORED false)  
416 - BR_PROPERTY(QString, regexp, "") 402 + if (value.isEmpty()) continue;
  403 + int count = statHash.value(value,0);
  404 + statHash.value(value,count+1);
  405 + }
  406 + }
  407 + foreach (const QString &key, statHash.keys()) fprintf(stdout, "%s: %s\n", qPrintable(key), qPrintable(statHash.value(key)));
  408 + }
417 409
418 void project(const Template &src, Template &dst) const 410 void project(const Template &src, Template &dst) const
419 { 411 {
420 dst = src; 412 dst = src;
421 - const QRegularExpression re(regexp);  
422 - foreach (const QString &key, dst.file.localKeys())  
423 - if (re.match(key).hasMatch())  
424 - dst.file.remove(key);  
425 } 413 }
426 }; 414 };
427 415
428 -BR_REGISTER(Transform, RemoveMetadataTransform) 416 +BR_REGISTER(Transform, MetadataStatisticsTransform)
429 417
430 /*! 418 /*!
431 * \ingroup transforms 419 * \ingroup transforms
openbr/plugins/output.cpp
@@ -76,14 +76,29 @@ class csvOutput : public MatrixOutput @@ -76,14 +76,29 @@ class csvOutput : public MatrixOutput
76 { 76 {
77 if (file.isNull() || targetFiles.isEmpty() || queryFiles.isEmpty()) return; 77 if (file.isNull() || targetFiles.isEmpty() || queryFiles.isEmpty()) return;
78 QStringList lines; 78 QStringList lines;
79 - lines.append("File," + targetFiles.names().join(","));  
80 - for (int i=0; i<queryFiles.size(); i++) {  
81 - QStringList words;  
82 - for (int j=0; j<targetFiles.size(); j++)  
83 - words.append(toString(i,j)); // The toString idiom is used to output match scores - see MatrixOutput  
84 - lines.append(queryFiles[i].name+","+words.join(",")); 79 + if (Globals->crossValidate == 0) {
  80 + for (int i=0; i<queryFiles.size(); i++) {
  81 + QStringList words;
  82 + for (int j=0; j<targetFiles.size(); j++)
  83 + words.append(queryFiles[i].name+","+targetFiles[j].baseName() + "," + toString(i,j)); // The toString idiom is used to output match scores - see MatrixOutput
  84 + lines.append(words.join("\n"));
  85 + }
  86 + QtUtils::writeFile(file.name, lines);
  87 + } else {
  88 + for (int k=0; k<Globals->crossValidate; k++) {
  89 + lines.clear();
  90 + for (int i=0; i<queryFiles.size(); i++) {
  91 + int queryPartition = queryFiles[i].get<int>("Partition");
  92 + if (queryPartition != k) continue;
  93 + QStringList words;
  94 + QList<int> targetPartitions = targetFiles.crossValidationPartitions();
  95 + for (int j=0; j<targetFiles.size(); j++)
  96 + if (queryPartition == targetPartitions[j]) words.append(queryFiles[i].name+","+targetFiles[j].baseName() + "," + toString(i,j)); // The toString idiom is used to output match scores - see MatrixOutput
  97 + lines.append(words.join("\n"));
  98 + }
  99 + QtUtils::writeFile(file.name.arg(QString::number(k)), lines);
  100 + }
85 } 101 }
86 - QtUtils::writeFile(file, lines);  
87 } 102 }
88 }; 103 };
89 104
@@ -249,7 +264,8 @@ BR_REGISTER(Output, mtxOutput) @@ -249,7 +264,8 @@ BR_REGISTER(Output, mtxOutput)
249 /*! 264 /*!
250 * \ingroup outputs 265 * \ingroup outputs
251 * \brief Rank retrieval output. 266 * \brief Rank retrieval output.
252 - * \author Josh Klontz \cite jklontz Scott Klum \cite sklum 267 + * \author Josh Klontz \cite jklontz
  268 + * \author Scott Klum \cite sklum
253 */ 269 */
254 class rrOutput : public MatrixOutput 270 class rrOutput : public MatrixOutput
255 { 271 {
openbr/plugins/random.cpp
@@ -56,7 +56,7 @@ class RndSubspaceTransform : public Transform @@ -56,7 +56,7 @@ class RndSubspaceTransform : public Transform
56 for (int i=0; i<size; i++) 56 for (int i=0; i<size; i++)
57 weights.append(1); 57 weights.append(1);
58 } 58 }
59 - const int dimsOut = weights.size()*fraction; 59 + const int dimsOut = std::max(int(weights.size()*fraction), 1);
60 60
61 QList<int> sample = Common::RandSample(dimsOut, weights); 61 QList<int> sample = Common::RandSample(dimsOut, weights);
62 Mat xMap(1, dimsOut, CV_16SC1); 62 Mat xMap(1, dimsOut, CV_16SC1);
openbr/plugins/stasm4.cpp
@@ -56,6 +56,8 @@ class StasmTransform : public UntrainableTransform @@ -56,6 +56,8 @@ class StasmTransform : public UntrainableTransform
56 56
57 Q_PROPERTY(bool stasm3Format READ get_stasm3Format WRITE set_stasm3Format RESET reset_stasm3Format STORED false) 57 Q_PROPERTY(bool stasm3Format READ get_stasm3Format WRITE set_stasm3Format RESET reset_stasm3Format STORED false)
58 BR_PROPERTY(bool, stasm3Format, false) 58 BR_PROPERTY(bool, stasm3Format, false)
  59 + Q_PROPERTY(bool clearLandmarks READ get_clearLandmarks WRITE set_clearLandmarks RESET reset_clearLandmarks STORED false)
  60 + BR_PROPERTY(bool, clearLandmarks, false)
59 61
60 Resource<StasmCascadeClassifier> stasmCascadeResource; 62 Resource<StasmCascadeClassifier> stasmCascadeResource;
61 63
@@ -69,6 +71,8 @@ class StasmTransform : public UntrainableTransform @@ -69,6 +71,8 @@ class StasmTransform : public UntrainableTransform
69 { 71 {
70 if (src.m().channels() != 1) qFatal("Stasm expects single channel matrices."); 72 if (src.m().channels() != 1) qFatal("Stasm expects single channel matrices.");
71 73
  74 + dst = src;
  75 +
72 StasmCascadeClassifier *stasmCascade = stasmCascadeResource.acquire(); 76 StasmCascadeClassifier *stasmCascade = stasmCascadeResource.acquire();
73 77
74 int foundface; 78 int foundface;
@@ -83,10 +87,20 @@ class StasmTransform : public UntrainableTransform @@ -83,10 +87,20 @@ class StasmTransform : public UntrainableTransform
83 87
84 stasmCascadeResource.release(stasmCascade); 88 stasmCascadeResource.release(stasmCascade);
85 89
86 - if (!foundface) qWarning("No face found in %s", qPrintable(src.file.fileName()));  
87 - else {  
88 - for (int i = 0; i < nLandmarks; i++)  
89 - dst.file.appendPoint(QPointF(landmarks[2 * i], landmarks[2 * i + 1])); 90 + if (clearLandmarks) {
  91 + dst.file.clearPoints();
  92 + dst.file.clearRects();
  93 + }
  94 +
  95 + if (!foundface) {
  96 + qWarning("No face found in %s", qPrintable(src.file.fileName()));
  97 + } else {
  98 + for (int i = 0; i < nLandmarks; i++) {
  99 + QPointF point(landmarks[2 * i], landmarks[2 * i + 1]);
  100 + dst.file.appendPoint(point);
  101 + if (i == 38) dst.file.set("StasmRightEye",point);
  102 + if (i == 39) dst.file.set("StasmLeftEye", point);
  103 + }
90 } 104 }
91 105
92 dst.m() = src.m(); 106 dst.m() = src.m();
openbr/plugins/template.cpp
1 #include "openbr_internal.h" 1 #include "openbr_internal.h"
  2 +#include <QRegularExpression>
2 3
3 namespace br 4 namespace br
4 { 5 {
@@ -25,6 +26,30 @@ class RetainTransform : public UntrainableTransform @@ -25,6 +26,30 @@ class RetainTransform : public UntrainableTransform
25 26
26 BR_REGISTER(Transform, RetainTransform) 27 BR_REGISTER(Transform, RetainTransform)
27 28
  29 +/*!
  30 + * \ingroup transforms
  31 + * \brief Remove templates with the specified file extension or metadata value.
  32 + * \author Josh Klontz \cite jklontz
  33 + */
  34 +class RemoveTemplatesTransform : public UntrainableMetaTransform
  35 +{
  36 + Q_OBJECT
  37 + Q_PROPERTY(QString regexp READ get_regexp WRITE set_regexp RESET reset_regexp STORED false)
  38 + Q_PROPERTY(QString key READ get_key WRITE set_key RESET reset_key STORED false)
  39 + BR_PROPERTY(QString, regexp, "")
  40 + BR_PROPERTY(QString, key, "")
  41 +
  42 + void project(const Template &src, Template &dst) const
  43 + {
  44 + const QRegularExpression re(regexp);
  45 + const QRegularExpressionMatch match = re.match(key.isEmpty() ? src.file.suffix() : src.file.get<QString>(key));
  46 + if (match.hasMatch()) dst = Template();
  47 + else dst = src;
  48 + }
  49 +};
  50 +
  51 +BR_REGISTER(Transform, RemoveTemplatesTransform)
  52 +
28 } // namespace br 53 } // namespace br
29 54
30 #include "template.moc" 55 #include "template.moc"