Commit 57423a277d90de6b7f9c46279013ffc746e125bd
1 parent
32b35bfb
Updated stasm to allow pinning of points
Showing
6 changed files
with
36 additions
and
53 deletions
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 &simmat, const Mat &mask, const QString &csv) | @@ -178,7 +176,7 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &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 &files, const File &destination, bool show) | @@ -228,7 +228,7 @@ bool Plot(const QStringList &files, const File &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 &files, const File &destination, bool show) | @@ -236,7 +236,7 @@ bool Plot(const QStringList &files, const File &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 |