Commit 57423a277d90de6b7f9c46279013ffc746e125bd

Authored by Scott Klum
1 parent 32b35bfb

Updated stasm to allow pinning of points

openbr/core/eval.cpp
@@ -114,8 +114,6 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv) @@ -114,8 +114,6 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv)
114 114
115 float result = -1; 115 float result = -1;
116 116
117 - qDebug() << simmat.rows << simmat.cols;  
118 -  
119 // Make comparisons 117 // Make comparisons
120 QList<Comparison> comparisons; comparisons.reserve(simmat.rows*simmat.cols); 118 QList<Comparison> comparisons; comparisons.reserve(simmat.rows*simmat.cols);
121 int genuineCount = 0, impostorCount = 0, numNaNs = 0; 119 int genuineCount = 0, impostorCount = 0, numNaNs = 0;
@@ -178,7 +176,7 @@ float Evaluate(const Mat &amp;simmat, const Mat &amp;mask, const QString &amp;csv) @@ -178,7 +176,7 @@ float Evaluate(const Mat &amp;simmat, const Mat &amp;mask, const QString &amp;csv)
178 if ((falsePositives > previousFalsePositives) && 176 if ((falsePositives > previousFalsePositives) &&
179 (truePositives > previousTruePositives)) { 177 (truePositives > previousTruePositives)) {
180 // Restrict the extreme ends of the curve 178 // Restrict the extreme ends of the curve
181 - //if ((truePositives >= 10) && (falsePositives < impostorCount/2)) 179 + if ((truePositives >= 10) && (falsePositives < impostorCount/2))
182 operatingPoints.append(OperatingPoint(thresh, float(falsePositives)/impostorCount, float(truePositives)/genuineCount)); 180 operatingPoints.append(OperatingPoint(thresh, float(falsePositives)/impostorCount, float(truePositives)/genuineCount));
183 previousFalsePositives = falsePositives; 181 previousFalsePositives = falsePositives;
184 previousTruePositives = truePositives; 182 previousTruePositives = truePositives;
openbr/core/plot.cpp
@@ -228,7 +228,7 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show) @@ -228,7 +228,7 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show)
228 QString(", xlab=\"False Accept Rate\", ylab=\"True Accept Rate\") + theme_minimal()") + 228 QString(", xlab=\"False Accept Rate\", ylab=\"True Accept Rate\") + theme_minimal()") +
229 (p.major.size > 1 ? getScale("colour", p.major.header, p.major.size) : QString()) + 229 (p.major.size > 1 ? getScale("colour", p.major.header, p.major.size) : QString()) +
230 (p.minor.size > 1 ? QString(" + scale_linetype_discrete(\"%1\")").arg(p.minor.header) : QString()) + 230 (p.minor.size > 1 ? QString(" + scale_linetype_discrete(\"%1\")").arg(p.minor.header) : QString()) +
231 - QString(" + scale_x_log10(labels=percent, limits=c(min(DET$X),1)) + scale_y_log10(labels=percent) + annotation_logticks()\n\n"))); 231 + QString(" + scale_x_log10(labels=percent, limits=c(min(DET$X),1)) + scale_y_continuous(labels=percent) + annotation_logticks(sides=\"b\")\n\n")));
232 232
233 p.file.write(qPrintable(QString("qplot(X, Y, data=DET%1").arg((p.major.smooth || p.minor.smooth) ? ", geom=\"smooth\", method=loess, level=0.99" : ", geom=\"line\"") + 233 p.file.write(qPrintable(QString("qplot(X, Y, data=DET%1").arg((p.major.smooth || p.minor.smooth) ? ", geom=\"smooth\", method=loess, level=0.99" : ", geom=\"line\"") +
234 (p.major.size > 1 ? QString(", colour=factor(%1)").arg(p.major.header) : QString()) + 234 (p.major.size > 1 ? QString(", colour=factor(%1)").arg(p.major.header) : QString()) +
@@ -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_continuous(labels=percent)\n\n"))); 239 + QString(" + scale_x_log10(labels=percent, limits=c(min(DET$X),1)) + scale_y_log10(labels=percent) + annotation_logticks()\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/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 +
  123 + stream << t;
123 } 124 }
124 }; 125 };
125 126
openbr/plugins/misc.cpp
@@ -382,35 +382,6 @@ BR_REGISTER(Transform, RegexPropertyTransform) @@ -382,35 +382,6 @@ BR_REGISTER(Transform, RegexPropertyTransform)
382 382
383 /*! 383 /*!
384 * \ingroup transforms 384 * \ingroup transforms
385 - * \brief Calculate metadata statistics  
386 - * \author Scott Klum \cite sklum  
387 - */  
388 -class MetadataStatisticsTransform : public UntrainableTransform  
389 -{  
390 - Q_OBJECT  
391 - Q_PROPERTY(QStringList keys READ get_keys WRITE set_keys RESET reset_keys STORED false)  
392 - BR_PROPERTY(QStringList, keys, QStringList())  
393 -  
394 - mutable QHash<QString,int> statHash;  
395 -  
396 - void project(const Template &src, Template &dst) const  
397 - {  
398 - dst = src;  
399 - foreach (const QString &key, keys) {  
400 - QString value = src.file.get<QString>(key, QString());  
401 -  
402 - if (value.isEmpty()) continue;  
403 - int count = statHash.value(value,0);  
404 - statHash.insert(value,count+1);  
405 - }  
406 - foreach (const QString &key, statHash.keys()) qDebug() << key << statHash.value(key);  
407 - }  
408 -};  
409 -  
410 -BR_REGISTER(Transform, MetadataStatisticsTransform)  
411 -  
412 -/*!  
413 - * \ingroup transforms  
414 * \brief Store the last matrix of the input template as a metadata key with input property name. 385 * \brief Store the last matrix of the input template as a metadata key with input property name.
415 * \author Charles Otto \cite caotto 386 * \author Charles Otto \cite caotto
416 */ 387 */
openbr/plugins/regions.cpp
@@ -348,7 +348,6 @@ class RectFromPointsTransform : public UntrainableTransform @@ -348,7 +348,6 @@ class RectFromPointsTransform : public UntrainableTransform
348 348
349 if (crop) dst.m() = src.m()(Rect(std::max(0.0, minX - deltaWidth/2.0), std::max(0.0, minY - deltaHeight/2.0), std::min((double)src.m().cols, width), std::min((double)src.m().rows, height))); 349 if (crop) dst.m() = src.m()(Rect(std::max(0.0, minX - deltaWidth/2.0), std::max(0.0, minY - deltaHeight/2.0), std::min((double)src.m().cols, width), std::min((double)src.m().rows, height)));
350 else { 350 else {
351 - qDebug() << QRectF(std::max(0.0, minX - deltaWidth/2.0), std::max(0.0, minY - deltaHeight/2.0), std::min((double)src.m().cols, width), std::min((double)src.m().rows, height)).size();  
352 dst.file.appendRect(QRectF(std::max(0.0, minX - deltaWidth/2.0), std::max(0.0, minY - deltaHeight/2.0), std::min((double)src.m().cols, width), std::min((double)src.m().rows, height))); 351 dst.file.appendRect(QRectF(std::max(0.0, minX - deltaWidth/2.0), std::max(0.0, minY - deltaHeight/2.0), std::min((double)src.m().cols, width), std::min((double)src.m().rows, height)));
353 dst.m() = src.m(); 352 dst.m() = src.m();
354 } 353 }
openbr/plugins/stasm4.cpp
@@ -58,6 +58,8 @@ class StasmTransform : public UntrainableTransform @@ -58,6 +58,8 @@ class StasmTransform : public UntrainableTransform
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) 59 Q_PROPERTY(bool clearLandmarks READ get_clearLandmarks WRITE set_clearLandmarks RESET reset_clearLandmarks STORED false)
60 BR_PROPERTY(bool, clearLandmarks, false) 60 BR_PROPERTY(bool, clearLandmarks, false)
  61 + Q_PROPERTY(QStringList pinEyes READ get_pinEyes WRITE set_pinEyes RESET reset_pinEyes STORED false)
  62 + BR_PROPERTY(QStringList, pinEyes, QStringList())
61 63
62 Resource<StasmCascadeClassifier> stasmCascadeResource; 64 Resource<StasmCascadeClassifier> stasmCascadeResource;
63 65
@@ -79,28 +81,41 @@ class StasmTransform : public UntrainableTransform @@ -79,28 +81,41 @@ class StasmTransform : public UntrainableTransform
79 int nLandmarks = stasm_NLANDMARKS; 81 int nLandmarks = stasm_NLANDMARKS;
80 float landmarks[2 * stasm_NLANDMARKS]; 82 float landmarks[2 * stasm_NLANDMARKS];
81 83
82 - bool pinned = true; 84 + if (!pinEyes.isEmpty()) {
  85 + // Two use cases are accounted for:
  86 + // 1. Pin eyes without normalization: in this case the string list should contain the KEYS for right then left eyes, respectively.
  87 + // 2. Pin eyes with normalization: in this case the string list should contain the COORDINATES of the right then left eyes, respectively.
  88 + // Note that for case 2, if Affine_0 and Affine_1 are not present (indicating no normalization has taken place), we default to stasm_search_single.
83 89
84 - if (pinned) {  
85 - if (src.file.contains("Affine_0")) {  
86 - float eyes[2 * stasm_NLANDMARKS]; 90 + bool ok = false;
  91 + QPointF rightEye;
  92 + QPointF leftEye;
87 93
88 - for (int i = 0; i < nLandmarks; i++) {  
89 - if (i == 38) { eyes[2*i] = 66.24; eyes[2*i+1] = 126; }  
90 - else if (i == 39) { eyes[2*i] = 125.76; eyes[2*i+1] = 126; }  
91 - else { eyes[2*i] = 0; eyes[2*i+1] = 0; } 94 + if (src.file.contains("Affine_0") && src.file.contains("Affine_1")) {
  95 + rightEye = QtUtils::toPoint(pinEyes.at(0),&ok);
  96 + leftEye = QtUtils::toPoint(pinEyes.at(1),&ok);
  97 + }
  98 +
  99 + if (!ok) {
  100 + rightEye = QtUtils::toPoint(src.file.get<QString>(pinEyes.at(0), QString()),&ok);
  101 + leftEye = QtUtils::toPoint(src.file.get<QString>(pinEyes.at(1), QString()),&ok);
92 } 102 }
93 103
  104 + float eyes[2 * stasm_NLANDMARKS];
  105 +
  106 + if (ok) {
  107 + for (int i = 0; i < nLandmarks; i++) {
  108 + if (i == 38) /*Stasm Right Eye*/ { eyes[2*i] = rightEye.x(); eyes[2*i+1] = rightEye.y(); }
  109 + else if (i == 39) /*Stasm Left Eye*/ { eyes[2*i] = leftEye.x(); eyes[2*i+1] = leftEye.y(); }
  110 + else { eyes[2*i] = 0; eyes[2*i+1] = 0; }
  111 + }
  112 + } else qFatal("Unable to interpret pinned eyes.");
  113 +
94 stasm_search_pinned(landmarks, eyes, reinterpret_cast<const char*>(src.m().data), src.m().cols, src.m().rows, NULL); 114 stasm_search_pinned(landmarks, eyes, reinterpret_cast<const char*>(src.m().data), src.m().cols, src.m().rows, NULL);
95 115
  116 + // The ASM in Stasm is guaranteed to converge in this case
96 foundface = 1; 117 foundface = 1;
97 - } else {  
98 - qDebug() << "Single search...";  
99 - stasm_search_single(&foundface, landmarks, reinterpret_cast<const char*>(src.m().data), src.m().cols, src.m().rows, *stasmCascade, NULL, NULL);  
100 - }  
101 - } else {  
102 - stasm_search_single(&foundface, landmarks, reinterpret_cast<const char*>(src.m().data), src.m().cols, src.m().rows, *stasmCascade, NULL, NULL);  
103 - } 118 + } stasm_search_single(&foundface, landmarks, reinterpret_cast<const char*>(src.m().data), src.m().cols, src.m().rows, *stasmCascade, NULL, NULL);
104 119
105 if (stasm3Format) { 120 if (stasm3Format) {
106 nLandmarks = 76; 121 nLandmarks = 76;
@@ -109,6 +124,7 @@ class StasmTransform : public UntrainableTransform @@ -109,6 +124,7 @@ class StasmTransform : public UntrainableTransform
109 124
110 stasmCascadeResource.release(stasmCascade); 125 stasmCascadeResource.release(stasmCascade);
111 126
  127 + // For convenience, if these are the only points/rects we want to deal with as the algorithm progresses
112 if (clearLandmarks) { 128 if (clearLandmarks) {
113 dst.file.clearPoints(); 129 dst.file.clearPoints();
114 dst.file.clearRects(); 130 dst.file.clearRects();
@@ -124,8 +140,6 @@ class StasmTransform : public UntrainableTransform @@ -124,8 +140,6 @@ class StasmTransform : public UntrainableTransform
124 else if (i == 39) dst.file.set("StasmLeftEye", point); 140 else if (i == 39) dst.file.set("StasmLeftEye", point);
125 } 141 }
126 } 142 }
127 -  
128 - dst.m() = src.m();  
129 } 143 }
130 }; 144 };
131 145