Commit fbb16fc3fc0271e0c6dd7f044fd0f4653cd8a1d5
Merge branch 'master' of https://github.com/biometrics/openbr into mosift
Showing
9 changed files
with
32 additions
and
89 deletions
CHANGELOG.md
| 1 | 0.4.0 - ??/??/?? | 1 | 0.4.0 - ??/??/?? |
| 2 | ================ | 2 | ================ |
| 3 | * Added -evalDetection and -plotDetection for evaluating and plotting object detection accuracy (#9) | 3 | * Added -evalDetection and -plotDetection for evaluating and plotting object detection accuracy (#9) |
| 4 | +* Deprecated Transform::backProject | ||
| 4 | 5 | ||
| 5 | 0.3.0 - 5/22/13 | 6 | 0.3.0 - 5/22/13 |
| 6 | =============== | 7 | =============== |
openbr/core/core.cpp
| @@ -146,13 +146,7 @@ struct AlgorithmCore | @@ -146,13 +146,7 @@ struct AlgorithmCore | ||
| 146 | data.removeAt(i); | 146 | data.removeAt(i); |
| 147 | const int numFiles = data.size(); | 147 | const int numFiles = data.size(); |
| 148 | 148 | ||
| 149 | - if (Globals->backProject) { | ||
| 150 | - TemplateList backProjectedData; | ||
| 151 | - transform->backProject(data, backProjectedData); | ||
| 152 | - data = backProjectedData; | ||
| 153 | - } else { | ||
| 154 | - data >> *transform; | ||
| 155 | - } | 149 | + data >> *transform; |
| 156 | 150 | ||
| 157 | g->writeBlock(data); | 151 | g->writeBlock(data); |
| 158 | const FileList newFiles = data.files(); | 152 | const FileList newFiles = data.files(); |
openbr/core/eval.cpp
| @@ -373,6 +373,8 @@ static QStringList computeDetectionResults(const QList<ResolvedDetection> &detec | @@ -373,6 +373,8 @@ static QStringList computeDetectionResults(const QList<ResolvedDetection> &detec | ||
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | const int keep = qMin(points.size(), Max_Points); | 375 | const int keep = qMin(points.size(), Max_Points); |
| 376 | + if (keep < 2) qFatal("Insufficient points."); | ||
| 377 | + | ||
| 376 | QStringList lines; lines.reserve(keep); | 378 | QStringList lines; lines.reserve(keep); |
| 377 | for (int i=0; i<keep; i++) { | 379 | for (int i=0; i<keep; i++) { |
| 378 | const DetectionOperatingPoint &point = points[double(i) / double(keep-1) * double(points.size()-1)]; | 380 | const DetectionOperatingPoint &point = points[double(i) / double(keep-1) * double(points.size()-1)]; |
| @@ -382,6 +384,15 @@ static QStringList computeDetectionResults(const QList<ResolvedDetection> &detec | @@ -382,6 +384,15 @@ static QStringList computeDetectionResults(const QList<ResolvedDetection> &detec | ||
| 382 | return lines; | 384 | return lines; |
| 383 | } | 385 | } |
| 384 | 386 | ||
| 387 | +QString getDetectKey(const TemplateList &templates) | ||
| 388 | +{ | ||
| 389 | + const File &f = templates.first().file; | ||
| 390 | + foreach (const QString &key, f.localKeys()) | ||
| 391 | + if (!f.get<QRectF>(key, QRectF()).isNull()) | ||
| 392 | + return key; | ||
| 393 | + return ""; | ||
| 394 | +} | ||
| 395 | + | ||
| 385 | float EvalDetection(const QString &predictedInput, const QString &truthInput, const QString &csv) | 396 | float EvalDetection(const QString &predictedInput, const QString &truthInput, const QString &csv) |
| 386 | { | 397 | { |
| 387 | qDebug("Evaluating detection of %s against %s", qPrintable(predictedInput), qPrintable(truthInput)); | 398 | qDebug("Evaluating detection of %s against %s", qPrintable(predictedInput), qPrintable(truthInput)); |
| @@ -389,20 +400,22 @@ float EvalDetection(const QString &predictedInput, const QString &truthInput, co | @@ -389,20 +400,22 @@ float EvalDetection(const QString &predictedInput, const QString &truthInput, co | ||
| 389 | const TemplateList truth(TemplateList::fromGallery(truthInput)); | 400 | const TemplateList truth(TemplateList::fromGallery(truthInput)); |
| 390 | 401 | ||
| 391 | // Figure out which metadata field contains a bounding box | 402 | // Figure out which metadata field contains a bounding box |
| 392 | - QString detectKey; | ||
| 393 | - foreach (const QString &key, truth.first().file.localKeys()) | ||
| 394 | - if (!truth.first().file.get<QRectF>(key, QRectF()).isNull()) { | ||
| 395 | - detectKey = key; | ||
| 396 | - break; | ||
| 397 | - } | ||
| 398 | - if (detectKey.isNull()) qFatal("No suitable metadata key found."); | ||
| 399 | - else qDebug("Using metadata key: %s", qPrintable(detectKey)); | 403 | + QString truthDetectKey = getDetectKey(truth); |
| 404 | + if (truthDetectKey.isEmpty()) qFatal("No suitable ground truth metadata key found."); | ||
| 405 | + QString predictedDetectKey = truthDetectKey; | ||
| 406 | + if (predicted.first().file.get<QRectF>(predictedDetectKey, QRectF()).isNull()) | ||
| 407 | + predictedDetectKey = getDetectKey(predicted); | ||
| 408 | + if (predictedDetectKey.isEmpty()) qFatal("No suitable predicted metadata key found."); | ||
| 409 | + | ||
| 410 | + qDebug("Using metadata key: %s%s", | ||
| 411 | + qPrintable(predictedDetectKey), | ||
| 412 | + qPrintable(predictedDetectKey == truthDetectKey ? QString() : "/"+truthDetectKey)); | ||
| 400 | 413 | ||
| 401 | QMap<QString, Detections> allDetections; // Organized by file, QMap used to preserve order | 414 | QMap<QString, Detections> allDetections; // Organized by file, QMap used to preserve order |
| 402 | foreach (const Template &t, predicted) | 415 | foreach (const Template &t, predicted) |
| 403 | - allDetections[t.file.baseName()].predicted.append(Detection(t.file.get<QRectF>(detectKey), t.file.get<float>("Confidence", -1))); | 416 | + allDetections[t.file.baseName()].predicted.append(Detection(t.file.get<QRectF>(predictedDetectKey), t.file.get<float>("Confidence", -1))); |
| 404 | foreach (const Template &t, truth) | 417 | foreach (const Template &t, truth) |
| 405 | - allDetections[t.file.baseName()].truth.append(Detection(t.file.get<QRectF>(detectKey))); | 418 | + allDetections[t.file.baseName()].truth.append(Detection(t.file.get<QRectF>(truthDetectKey))); |
| 406 | 419 | ||
| 407 | QList<ResolvedDetection> resolvedDetections, falseNegativeDetections; | 420 | QList<ResolvedDetection> resolvedDetections, falseNegativeDetections; |
| 408 | foreach (Detections detections, allDetections.values()) { | 421 | foreach (Detections detections, allDetections.values()) { |
openbr/core/qtutils.cpp
| @@ -334,8 +334,8 @@ QRectF QtUtils::toRect(const QString &string, bool *ok) | @@ -334,8 +334,8 @@ QRectF QtUtils::toRect(const QString &string, bool *ok) | ||
| 334 | bool okX, okY, okWidth, okHeight; | 334 | bool okX, okY, okWidth, okHeight; |
| 335 | x = words[0].toFloat(&okX); | 335 | x = words[0].toFloat(&okX); |
| 336 | y = words[1].toFloat(&okY); | 336 | y = words[1].toFloat(&okY); |
| 337 | - width = words[0].toFloat(&okWidth); | ||
| 338 | - height = words[1].toFloat(&okHeight); | 337 | + width = words[2].toFloat(&okWidth); |
| 338 | + height = words[3].toFloat(&okHeight); | ||
| 339 | if (okX && okY && okWidth && okHeight) { | 339 | if (okX && okY && okWidth && okHeight) { |
| 340 | if (ok) *ok = true; | 340 | if (ok) *ok = true; |
| 341 | return QRectF(x, y, width, height); | 341 | return QRectF(x, y, width, height); |
openbr/openbr_plugin.cpp
| @@ -1171,28 +1171,6 @@ void Transform::project(const TemplateList &src, TemplateList &dst) const | @@ -1171,28 +1171,6 @@ void Transform::project(const TemplateList &src, TemplateList &dst) const | ||
| 1171 | futures.waitForFinished(); | 1171 | futures.waitForFinished(); |
| 1172 | } | 1172 | } |
| 1173 | 1173 | ||
| 1174 | -static void _backProject(const Transform *transform, const Template *dst, Template *src) | ||
| 1175 | -{ | ||
| 1176 | - try { | ||
| 1177 | - transform->backProject(*dst, *src); | ||
| 1178 | - } catch (...) { | ||
| 1179 | - qWarning("Exception triggered when processing %s with transform %s", qPrintable(src->file.flat()), qPrintable(transform->objectName())); | ||
| 1180 | - *src = Template(dst->file); | ||
| 1181 | - src->file.set("FTE", true); | ||
| 1182 | - } | ||
| 1183 | -} | ||
| 1184 | - | ||
| 1185 | -void Transform::backProject(const TemplateList &dst, TemplateList &src) const | ||
| 1186 | -{ | ||
| 1187 | - src.reserve(dst.size()); | ||
| 1188 | - for (int i=0; i<dst.size(); i++) src.append(Template()); | ||
| 1189 | - | ||
| 1190 | - QFutureSynchronizer<void> futures; | ||
| 1191 | - for (int i=0; i<dst.size(); i++) | ||
| 1192 | - futures.addFuture(QtConcurrent::run(_backProject, this, &dst[i], &src[i])); | ||
| 1193 | - futures.waitForFinished(); | ||
| 1194 | -} | ||
| 1195 | - | ||
| 1196 | QList<Transform *> Transform::getChildren() const | 1174 | QList<Transform *> Transform::getChildren() const |
| 1197 | { | 1175 | { |
| 1198 | QList<Transform *> output; | 1176 | QList<Transform *> output; |
openbr/openbr_plugin.h
| @@ -602,13 +602,6 @@ public: | @@ -602,13 +602,6 @@ public: | ||
| 602 | BR_PROPERTY(int, blockSize, parallelism * ((sizeof(void*) == 4) ? 128 : 1024)) | 602 | BR_PROPERTY(int, blockSize, parallelism * ((sizeof(void*) == 4) ? 128 : 1024)) |
| 603 | 603 | ||
| 604 | /*! | 604 | /*! |
| 605 | - * \brief true if backProject should be used instead of project (the algorithm should be inverted) | ||
| 606 | - */ | ||
| 607 | - Q_PROPERTY(bool backProject READ get_backProject WRITE set_backProject RESET reset_backProject) | ||
| 608 | - BR_PROPERTY(bool, backProject, false) | ||
| 609 | - | ||
| 610 | - | ||
| 611 | - /*! | ||
| 612 | * \brief If \c true no messages will be sent to the terminal, \c false by default. | 605 | * \brief If \c true no messages will be sent to the terminal, \c false by default. |
| 613 | */ | 606 | */ |
| 614 | Q_PROPERTY(bool quiet READ get_quiet WRITE set_quiet RESET reset_quiet) | 607 | Q_PROPERTY(bool quiet READ get_quiet WRITE set_quiet RESET reset_quiet) |
| @@ -1034,6 +1027,10 @@ private: | @@ -1034,6 +1027,10 @@ private: | ||
| 1034 | * @{ | 1027 | * @{ |
| 1035 | */ | 1028 | */ |
| 1036 | 1029 | ||
| 1030 | +/*! | ||
| 1031 | + * \brief For asynchronous events during template projection. | ||
| 1032 | + * \see #Transform::getEvent | ||
| 1033 | + */ | ||
| 1037 | class TemplateEvent : public QObject | 1034 | class TemplateEvent : public QObject |
| 1038 | { | 1035 | { |
| 1039 | Q_OBJECT | 1036 | Q_OBJECT |
| @@ -1048,7 +1045,6 @@ signals: | @@ -1048,7 +1045,6 @@ signals: | ||
| 1048 | void theSignal(const Template & output) const; | 1045 | void theSignal(const Template & output) const; |
| 1049 | }; | 1046 | }; |
| 1050 | 1047 | ||
| 1051 | - | ||
| 1052 | /*! | 1048 | /*! |
| 1053 | * \brief Plugin base class for processing a template. | 1049 | * \brief Plugin base class for processing a template. |
| 1054 | * | 1050 | * |
| @@ -1078,8 +1074,6 @@ public: | @@ -1078,8 +1074,6 @@ public: | ||
| 1078 | virtual void train(const TemplateList &data) = 0; /*!< \brief Train the transform. */ | 1074 | virtual void train(const TemplateList &data) = 0; /*!< \brief Train the transform. */ |
| 1079 | virtual void project(const Template &src, Template &dst) const = 0; /*!< \brief Apply the transform. */ | 1075 | virtual void project(const Template &src, Template &dst) const = 0; /*!< \brief Apply the transform. */ |
| 1080 | virtual void project(const TemplateList &src, TemplateList &dst) const; /*!< \brief Apply the transform. */ | 1076 | virtual void project(const TemplateList &src, TemplateList &dst) const; /*!< \brief Apply the transform. */ |
| 1081 | - virtual void backProject(const Template &dst, Template &src) const { src = dst; } /*!< \brief Invert the transform. */ | ||
| 1082 | - virtual void backProject(const TemplateList &dst, TemplateList &src) const; /*!< \brief Invert the transform. */ | ||
| 1083 | 1077 | ||
| 1084 | /*!< \brief Apply the transform, may update the transform's internal state */ | 1078 | /*!< \brief Apply the transform, may update the transform's internal state */ |
| 1085 | virtual void projectUpdate(const Template &src, Template &dst) | 1079 | virtual void projectUpdate(const Template &src, Template &dst) |
openbr/plugins/cascade.cpp
| @@ -98,7 +98,7 @@ class CascadeTransform : public UntrainableMetaTransform | @@ -98,7 +98,7 @@ class CascadeTransform : public UntrainableMetaTransform | ||
| 98 | for (size_t j=0; j<rects.size(); j++) { | 98 | for (size_t j=0; j<rects.size(); j++) { |
| 99 | Template u(t.file, m); | 99 | Template u(t.file, m); |
| 100 | if (rejectLevels.size() > j) | 100 | if (rejectLevels.size() > j) |
| 101 | - u.file.set("Confidence", rejectLevels[j]*1000.0 + levelWeights[j]*1.0); | 101 | + u.file.set("Confidence", rejectLevels[j]*levelWeights[j]); |
| 102 | const QRectF rect = OpenCVUtils::fromRect(rects[j]); | 102 | const QRectF rect = OpenCVUtils::fromRect(rects[j]); |
| 103 | u.file.appendRect(rect); | 103 | u.file.appendRect(rect); |
| 104 | u.file.set(model, rect); | 104 | u.file.set(model, rect); |
openbr/plugins/eigen3.cpp
| @@ -59,21 +59,6 @@ public: | @@ -59,21 +59,6 @@ public: | ||
| 59 | PCATransform() : keep(0.95), drop(0), whiten(false) {} | 59 | PCATransform() : keep(0.95), drop(0), whiten(false) {} |
| 60 | 60 | ||
| 61 | private: | 61 | private: |
| 62 | - /* | ||
| 63 | - void backProject(const Template &src, Template &dst) const | ||
| 64 | - { | ||
| 65 | - const cv::Mat &m = src; | ||
| 66 | - dst = cv::Mat(originalRows, m.rows*m.cols/originalRows, CV_32FC1); | ||
| 67 | - | ||
| 68 | - // Map Eigen into OpenCV | ||
| 69 | - Eigen::Map<const Eigen::MatrixXf> inMap(m.ptr<float>(), keep, 1); | ||
| 70 | - Eigen::Map<Eigen::MatrixXf> outMap(dst.m().ptr<float>(), m.rows*m.cols, 1); | ||
| 71 | - | ||
| 72 | - // Do projection | ||
| 73 | - outMap = (eVecs * inMap) + mean; | ||
| 74 | - } | ||
| 75 | - */ | ||
| 76 | - | ||
| 77 | double residualReconstructionError(const Template &src) const | 62 | double residualReconstructionError(const Template &src) const |
| 78 | { | 63 | { |
| 79 | Template proj; | 64 | Template proj; |
openbr/plugins/meta.cpp
| @@ -129,26 +129,6 @@ class PipeTransform : public CompositeTransform | @@ -129,26 +129,6 @@ class PipeTransform : public CompositeTransform | ||
| 129 | } | 129 | } |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | - void backProject(const Template &dst, Template &src) const | ||
| 133 | - { | ||
| 134 | - // Backprojecting a time-varying transform is probably not going to work. | ||
| 135 | - if (timeVarying()) qFatal("No backProject defined for time-varying transform"); | ||
| 136 | - | ||
| 137 | - src = dst; | ||
| 138 | - // Reverse order in which transforms are processed | ||
| 139 | - int length = transforms.length(); | ||
| 140 | - for (int i=length-1; i>=0; i--) { | ||
| 141 | - Transform *f = transforms.at(i); | ||
| 142 | - try { | ||
| 143 | - src >> *f; | ||
| 144 | - } catch (...) { | ||
| 145 | - qWarning("Exception triggered when processing %s with transform %s", qPrintable(dst.file.flat()), qPrintable(f->objectName())); | ||
| 146 | - src = Template(src.file); | ||
| 147 | - src.file.set("FTE", true); | ||
| 148 | - } | ||
| 149 | - } | ||
| 150 | - } | ||
| 151 | - | ||
| 152 | void projectUpdate(const Template &src, Template &dst) | 132 | void projectUpdate(const Template &src, Template &dst) |
| 153 | { | 133 | { |
| 154 | dst = src; | 134 | dst = src; |
| @@ -306,8 +286,6 @@ class ForkTransform : public CompositeTransform | @@ -306,8 +286,6 @@ class ForkTransform : public CompositeTransform | ||
| 306 | futures.waitForFinished(); | 286 | futures.waitForFinished(); |
| 307 | } | 287 | } |
| 308 | 288 | ||
| 309 | - void backProject(const Template &dst, Template &src) const {Transform::backProject(dst, src);} | ||
| 310 | - | ||
| 311 | // same as _project, but calls projectUpdate on sub-transforms | 289 | // same as _project, but calls projectUpdate on sub-transforms |
| 312 | void projectupdate(const Template & src, Template & dst) | 290 | void projectupdate(const Template & src, Template & dst) |
| 313 | { | 291 | { |