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 114  
115 115 float result = -1;
116 116  
117   - qDebug() << simmat.rows << simmat.cols;
118   -
119 117 // Make comparisons
120 118 QList<Comparison> comparisons; comparisons.reserve(simmat.rows*simmat.cols);
121 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 176 if ((falsePositives > previousFalsePositives) &&
179 177 (truePositives > previousTruePositives)) {
180 178 // Restrict the extreme ends of the curve
181   - //if ((truePositives >= 10) && (falsePositives < impostorCount/2))
  179 + if ((truePositives >= 10) && (falsePositives < impostorCount/2))
182 180 operatingPoints.append(OperatingPoint(thresh, float(falsePositives)/impostorCount, float(truePositives)/genuineCount));
183 181 previousFalsePositives = falsePositives;
184 182 previousTruePositives = truePositives;
... ...
openbr/core/plot.cpp
... ... @@ -228,7 +228,7 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show)
228 228 QString(", xlab=\"False Accept Rate\", ylab=\"True Accept Rate\") + theme_minimal()") +
229 229 (p.major.size > 1 ? getScale("colour", p.major.header, p.major.size) : QString()) +
230 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 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 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 236 QString(", xlab=\"False Accept Rate\", ylab=\"False Reject Rate\") + geom_abline(alpha=0.5, colour=\"grey\", linetype=\"dashed\") + theme_minimal()") +
237 237 (p.major.size > 1 ? getScale("colour", p.major.header, p.major.size) : QString()) +
238 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 241 p.file.write(qPrintable(QString("qplot(X, data=SD, geom=\"histogram\", fill=Y, position=\"identity\", alpha=I(1/2)") +
242 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 119 {
120 120 if (t.isEmpty() && t.file.isNull())
121 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 382  
383 383 /*!
384 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 385 * \brief Store the last matrix of the input template as a metadata key with input property name.
415 386 * \author Charles Otto \cite caotto
416 387 */
... ...
openbr/plugins/regions.cpp
... ... @@ -348,7 +348,6 @@ class RectFromPointsTransform : public UntrainableTransform
348 348  
349 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 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 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 352 dst.m() = src.m();
354 353 }
... ...
openbr/plugins/stasm4.cpp
... ... @@ -58,6 +58,8 @@ class StasmTransform : public UntrainableTransform
58 58 BR_PROPERTY(bool, stasm3Format, false)
59 59 Q_PROPERTY(bool clearLandmarks READ get_clearLandmarks WRITE set_clearLandmarks RESET reset_clearLandmarks STORED false)
60 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 64 Resource<StasmCascadeClassifier> stasmCascadeResource;
63 65  
... ... @@ -79,28 +81,41 @@ class StasmTransform : public UntrainableTransform
79 81 int nLandmarks = stasm_NLANDMARKS;
80 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 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 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 120 if (stasm3Format) {
106 121 nLandmarks = 76;
... ... @@ -109,6 +124,7 @@ class StasmTransform : public UntrainableTransform
109 124  
110 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 128 if (clearLandmarks) {
113 129 dst.file.clearPoints();
114 130 dst.file.clearRects();
... ... @@ -124,8 +140,6 @@ class StasmTransform : public UntrainableTransform
124 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  
... ...