Commit bee4a6fe0b4c0f60b9ceb9d8560e706b307e0fe0
1 parent
a31c2022
Updates
Showing
14 changed files
with
108 additions
and
61 deletions
openbr/core/bee.cpp
| ... | ... | @@ -112,7 +112,7 @@ void BEE::writeSigset(const QString &sigset, const br::FileList &files, bool ign |
| 112 | 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 | 116 | lines.append("\t\t<presentation file-name=\"" + file.name + "\" " + metadata.join(" ") + "/>"); |
| 117 | 117 | lines.append("\t</biometric-signature>"); |
| 118 | 118 | } | ... | ... |
openbr/core/eval.cpp
| ... | ... | @@ -167,7 +167,7 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv) |
| 167 | 167 | if ((falsePositives > previousFalsePositives) && |
| 168 | 168 | (truePositives > previousTruePositives)) { |
| 169 | 169 | // Restrict the extreme ends of the curve |
| 170 | - if ((truePositives >= 10) && (falsePositives < impostorCount/2)) | |
| 170 | + //if ((truePositives >= 10) && (falsePositives < impostorCount/2)) | |
| 171 | 171 | operatingPoints.append(OperatingPoint(thresh, float(falsePositives)/impostorCount, float(truePositives)/genuineCount)); |
| 172 | 172 | previousFalsePositives = falsePositives; |
| 173 | 173 | previousTruePositives = truePositives; | ... | ... |
openbr/core/plot.cpp
| ... | ... | @@ -236,7 +236,7 @@ bool Plot(const QStringList &files, const File &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_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 | 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/openbr_plugin.cpp
| ... | ... | @@ -441,10 +441,10 @@ TemplateList TemplateList::fromGallery(const br::File &gallery) |
| 441 | 441 | // of target images to every partition |
| 442 | 442 | newTemplates[i].file.set("Partition", -1); |
| 443 | 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 | 60 | |
| 61 | 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 | 310 | Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false) |
| 311 | 311 | Q_PROPERTY(float alpha READ get_alpha WRITE set_alpha RESET reset_alpha STORED false) |
| 312 | 312 | BR_PROPERTY(br::Distance*, distance, NULL) |
| 313 | - BR_PROPERTY(float, alpha, 0.1f); | |
| 313 | + BR_PROPERTY(float, alpha, 0.1f) | |
| 314 | 314 | |
| 315 | 315 | mutable QHash<QString,float> scoreHash; |
| 316 | 316 | mutable QMutex mutex; | ... | ... |
openbr/plugins/draw.cpp
| ... | ... | @@ -46,11 +46,11 @@ class DrawTransform : public UntrainableTransform |
| 46 | 46 | void project(const Template &src, Template &dst) const |
| 47 | 47 | { |
| 48 | 48 | const Scalar color(0,255,0); |
| 49 | - const Scalar verboseColor(255, 255, 0); | |
| 49 | + const Scalar verboseColor(0, 0, 0); | |
| 50 | 50 | dst.m() = inPlace ? src.m() : src.m().clone(); |
| 51 | 51 | |
| 52 | 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 | 54 | for (int i=0; i<pointsList.size(); i++) { |
| 55 | 55 | const Point2f &point = pointsList[i]; |
| 56 | 56 | circle(dst, point, 3, color, -1); | ... | ... |
openbr/plugins/filter.cpp
| ... | ... | @@ -139,10 +139,8 @@ class CSDNTransform : public UntrainableTransform |
| 139 | 139 | |
| 140 | 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 | 144 | int width = min( j+surround, nCols ) - max( 0, j-surround ); |
| 147 | 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 | 119 | { |
| 120 | 120 | if (t.isEmpty() && t.file.isNull()) |
| 121 | 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 | 186 | if (file.name.isEmpty()) return; |
| 186 | 187 | |
| 187 | 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 | 190 | destination += (newFormat.isEmpty() ? t.file.fileName() : t.file.baseName()+newFormat); |
| 190 | 191 | |
| 191 | 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 | 382 | |
| 383 | 383 | /*! |
| 384 | 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 | 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 | 410 | void project(const Template &src, Template &dst) const |
| 419 | 411 | { |
| 420 | 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 | 419 | * \ingroup transforms | ... | ... |
openbr/plugins/output.cpp
| ... | ... | @@ -76,14 +76,29 @@ class csvOutput : public MatrixOutput |
| 76 | 76 | { |
| 77 | 77 | if (file.isNull() || targetFiles.isEmpty() || queryFiles.isEmpty()) return; |
| 78 | 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 | 264 | /*! |
| 250 | 265 | * \ingroup outputs |
| 251 | 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 | 270 | class rrOutput : public MatrixOutput |
| 255 | 271 | { | ... | ... |
openbr/plugins/random.cpp
| ... | ... | @@ -56,7 +56,7 @@ class RndSubspaceTransform : public Transform |
| 56 | 56 | for (int i=0; i<size; i++) |
| 57 | 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 | 61 | QList<int> sample = Common::RandSample(dimsOut, weights); |
| 62 | 62 | Mat xMap(1, dimsOut, CV_16SC1); | ... | ... |
openbr/plugins/stasm4.cpp
| ... | ... | @@ -56,6 +56,8 @@ class StasmTransform : public UntrainableTransform |
| 56 | 56 | |
| 57 | 57 | Q_PROPERTY(bool stasm3Format READ get_stasm3Format WRITE set_stasm3Format RESET reset_stasm3Format STORED false) |
| 58 | 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 | 62 | Resource<StasmCascadeClassifier> stasmCascadeResource; |
| 61 | 63 | |
| ... | ... | @@ -69,6 +71,8 @@ class StasmTransform : public UntrainableTransform |
| 69 | 71 | { |
| 70 | 72 | if (src.m().channels() != 1) qFatal("Stasm expects single channel matrices."); |
| 71 | 73 | |
| 74 | + dst = src; | |
| 75 | + | |
| 72 | 76 | StasmCascadeClassifier *stasmCascade = stasmCascadeResource.acquire(); |
| 73 | 77 | |
| 74 | 78 | int foundface; |
| ... | ... | @@ -83,10 +87,20 @@ class StasmTransform : public UntrainableTransform |
| 83 | 87 | |
| 84 | 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 | 106 | dst.m() = src.m(); | ... | ... |
openbr/plugins/template.cpp
| 1 | 1 | #include "openbr_internal.h" |
| 2 | +#include <QRegularExpression> | |
| 2 | 3 | |
| 3 | 4 | namespace br |
| 4 | 5 | { |
| ... | ... | @@ -25,6 +26,30 @@ class RetainTransform : public UntrainableTransform |
| 25 | 26 | |
| 26 | 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 | 53 | } // namespace br |
| 29 | 54 | |
| 30 | 55 | #include "template.moc" | ... | ... |