Commit 0645316a10983c3b3a1ca67aca9edc9f2e8ead37
Merge branch 'master' of https://github.com/biometrics/openbr
Showing
5 changed files
with
78 additions
and
40 deletions
openbr/core/qtutils.cpp
| @@ -285,25 +285,45 @@ void QtUtils::checkArgsSize(const QString &name, const QStringList &args, int mi | @@ -285,25 +285,45 @@ void QtUtils::checkArgsSize(const QString &name, const QStringList &args, int mi | ||
| 285 | if (args.size() > max) qFatal("%s expects no more than %d arguments, got %d", qPrintable(name), max, args.size()); | 285 | if (args.size() > max) qFatal("%s expects no more than %d arguments, got %d", qPrintable(name), max, args.size()); |
| 286 | } | 286 | } |
| 287 | 287 | ||
| 288 | -QPointF QtUtils::toPoint(const QString &string) | 288 | +QPointF QtUtils::toPoint(const QString &string, bool *ok) |
| 289 | { | 289 | { |
| 290 | - QStringList values = string.split(','); | ||
| 291 | - if (values.size() == 2) { | ||
| 292 | - values[1].chop(1); | ||
| 293 | - return QPointF(values[0].mid(1).toFloat(), values[1].toFloat()); | 290 | + if (string.startsWith('(') && string.endsWith(')')) { |
| 291 | + const QStringList words = parse(string.mid(1, string.size()-2)); | ||
| 292 | + if (words.size() == 2) { | ||
| 293 | + float x, y; | ||
| 294 | + bool okX, okY; | ||
| 295 | + x = words[0].toFloat(&okX); | ||
| 296 | + y = words[1].toFloat(&okY); | ||
| 297 | + if (okX && okY) { | ||
| 298 | + if (ok) *ok = true; | ||
| 299 | + return QPointF(x, y); | ||
| 300 | + } | ||
| 301 | + } | ||
| 294 | } | 302 | } |
| 295 | - else qFatal("Failed to convert %s to QPointF format.", qPrintable(string)); | 303 | + |
| 304 | + if (ok) *ok = false; | ||
| 296 | return QPointF(); | 305 | return QPointF(); |
| 297 | } | 306 | } |
| 298 | 307 | ||
| 299 | -QRectF QtUtils::toRect(const QString &string) | 308 | +QRectF QtUtils::toRect(const QString &string, bool *ok) |
| 300 | { | 309 | { |
| 301 | - QStringList values = string.split(','); | ||
| 302 | - if (values.size() == 4) { | ||
| 303 | - values[3].chop(1); | ||
| 304 | - return QRectF(values[0].mid(1).toFloat(), values[1].toFloat(), values[2].toFloat(), values[3].toFloat()); | 310 | + if (string.startsWith('(') && string.endsWith(')')) { |
| 311 | + const QStringList words = parse(string.mid(1, string.size()-2)); | ||
| 312 | + if (words.size() == 4) { | ||
| 313 | + float x, y, width, height; | ||
| 314 | + bool okX, okY, okWidth, okHeight; | ||
| 315 | + x = words[0].toFloat(&okX); | ||
| 316 | + y = words[1].toFloat(&okY); | ||
| 317 | + width = words[0].toFloat(&okWidth); | ||
| 318 | + height = words[1].toFloat(&okHeight); | ||
| 319 | + if (okX && okY && okWidth && okHeight) { | ||
| 320 | + if (ok) *ok = true; | ||
| 321 | + return QRectF(x, y, width, height); | ||
| 322 | + } | ||
| 323 | + } | ||
| 305 | } | 324 | } |
| 306 | - else qFatal("Failed to convert %s to QRectF format.", qPrintable(string)); | 325 | + |
| 326 | + if (ok) *ok = false; | ||
| 307 | return QRectF(); | 327 | return QRectF(); |
| 308 | } | 328 | } |
| 309 | 329 |
openbr/core/qtutils.h
| @@ -62,8 +62,8 @@ namespace QtUtils | @@ -62,8 +62,8 @@ namespace QtUtils | ||
| 62 | QString shortTextHash(QString string); | 62 | QString shortTextHash(QString string); |
| 63 | QStringList parse(QString args, char split = ','); | 63 | QStringList parse(QString args, char split = ','); |
| 64 | void checkArgsSize(const QString &name, const QStringList &args, int min, int max); | 64 | void checkArgsSize(const QString &name, const QStringList &args, int min, int max); |
| 65 | - QPointF toPoint(const QString &string); | ||
| 66 | - QRectF toRect(const QString &string); | 65 | + QPointF toPoint(const QString &string, bool *ok = NULL); |
| 66 | + QRectF toRect(const QString &string, bool *ok = NULL); | ||
| 67 | 67 | ||
| 68 | /**** Process Utilities ****/ | 68 | /**** Process Utilities ****/ |
| 69 | bool runRScript(const QString &file); | 69 | bool runRScript(const QString &file); |
openbr/openbr_plugin.cpp
| @@ -125,6 +125,18 @@ QVariant File::value(const QString &key) const | @@ -125,6 +125,18 @@ QVariant File::value(const QString &key) const | ||
| 125 | return m_metadata.contains(key) ? m_metadata.value(key) : Globals->property(qPrintable(key)); | 125 | return m_metadata.contains(key) ? m_metadata.value(key) : Globals->property(qPrintable(key)); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | +QVariant File::parse(const QString &value) | ||
| 129 | +{ | ||
| 130 | + bool ok; | ||
| 131 | + const QPointF point = QtUtils::toPoint(value, &ok); | ||
| 132 | + if (ok) return point; | ||
| 133 | + const QRectF rect = QtUtils::toRect(value, &ok); | ||
| 134 | + if (ok) return rect; | ||
| 135 | + const float f = value.toFloat(&ok); | ||
| 136 | + if (ok) return f; | ||
| 137 | + return value; | ||
| 138 | +} | ||
| 139 | + | ||
| 128 | void File::set(const QString &key, const QVariant &value) | 140 | void File::set(const QString &key, const QVariant &value) |
| 129 | { | 141 | { |
| 130 | if (key == "Label") { | 142 | if (key == "Label") { |
| @@ -145,35 +157,16 @@ void File::set(const QString &key, const QVariant &value) | @@ -145,35 +157,16 @@ void File::set(const QString &key, const QVariant &value) | ||
| 145 | m_metadata.insert(key, value); | 157 | m_metadata.insert(key, value); |
| 146 | } | 158 | } |
| 147 | 159 | ||
| 148 | -// Note that we assume all values within a parameter list are the same type | ||
| 149 | void File::set(const QString &key, const QString &value) | 160 | void File::set(const QString &key, const QString &value) |
| 150 | { | 161 | { |
| 151 | - if (value[0] == '[') /* QVariantList */ { | ||
| 152 | - QStringList values = value.mid(1, value.size()-2).split(", "); | 162 | + if (value.startsWith('[') && value.endsWith(']')) { |
| 153 | QList<QVariant> variants; | 163 | QList<QVariant> variants; |
| 154 | - if (values[0][0] == '(') /* List of Points or Rects */ { | ||
| 155 | - if (values[0].split(',').size() == 2) /* List of Points */ foreach(const QString &word, values) variants.append(QtUtils::toPoint(word)); | ||
| 156 | - else if (values[0].split(',').size() == 4) /* List of Rects */ foreach(const QString &word, values) variants.append(QtUtils::toRect(word)); | ||
| 157 | - else qFatal("Incorrect landmark format."); | ||
| 158 | - } | ||
| 159 | - else { | ||
| 160 | - bool ok; | ||
| 161 | - foreach(const QString &word, values) { | ||
| 162 | - variants.append(word.toFloat(&ok)); | ||
| 163 | - if (!ok) { | ||
| 164 | - m_metadata.insert(key, value.split(", ")); | ||
| 165 | - return; | ||
| 166 | - } | ||
| 167 | - } | ||
| 168 | - } | ||
| 169 | - m_metadata.insert(key, variants); | ||
| 170 | - } | ||
| 171 | - else if (value[0] == '(') /* Point or Rect */ { | ||
| 172 | - if (value.split(',').size() == 2) /* QPointF */ m_metadata.insert(key, QtUtils::toPoint(value)); | ||
| 173 | - else if (value.split(',').size() == 4) /* QRectF */ m_metadata.insert(key, QtUtils::toRect(value)); | ||
| 174 | - else qFatal("Incorrect landmark format."); | 164 | + foreach (const QString &value, QtUtils::parse(value.mid(1, value.size()-2))) |
| 165 | + variants.append(parse(value)); | ||
| 166 | + set(key, QVariant(variants)); | ||
| 167 | + } else { | ||
| 168 | + set(key, QVariant(parse(value))); | ||
| 175 | } | 169 | } |
| 176 | - else m_metadata.insert(key, value); | ||
| 177 | } | 170 | } |
| 178 | 171 | ||
| 179 | bool File::getBool(const QString &key, bool defaultValue) const | 172 | bool File::getBool(const QString &key, bool defaultValue) const |
| @@ -294,7 +287,7 @@ void File::init(const QString &file) | @@ -294,7 +287,7 @@ void File::init(const QString &file) | ||
| 294 | if (unnamed) setParameter(i, words[0]); | 287 | if (unnamed) setParameter(i, words[0]); |
| 295 | else set(words[0], QVariant()); | 288 | else set(words[0], QVariant()); |
| 296 | } else { | 289 | } else { |
| 297 | - set(words[0],words[1]); | 290 | + set(words[0], words[1]); |
| 298 | } | 291 | } |
| 299 | } | 292 | } |
| 300 | name = name.left(index); | 293 | name = name.left(index); |
openbr/openbr_plugin.h
| @@ -194,6 +194,7 @@ struct BR_EXPORT File | @@ -194,6 +194,7 @@ struct BR_EXPORT File | ||
| 194 | 194 | ||
| 195 | bool contains(const QString &key) const; /*!< \brief Returns \c true if the key has an associated value, \c false otherwise. */ | 195 | bool contains(const QString &key) const; /*!< \brief Returns \c true if the key has an associated value, \c false otherwise. */ |
| 196 | QVariant value(const QString &key) const; /*!< \brief Returns the value for the specified key. */ | 196 | QVariant value(const QString &key) const; /*!< \brief Returns the value for the specified key. */ |
| 197 | + static QVariant parse(const QString &value); /*!< \brief Try to convert the QString to a QPointF or QRectF if possible. */ | ||
| 197 | void set(const QString &key, const QVariant &value); /*!< \brief Insert or overwrite the metadata key with the specified value. */ | 198 | void set(const QString &key, const QVariant &value); /*!< \brief Insert or overwrite the metadata key with the specified value. */ |
| 198 | void set(const QString &key, const QString &value); /*!< \brief Insert or overwrite the metadata key with the specified value. */ | 199 | void set(const QString &key, const QString &value); /*!< \brief Insert or overwrite the metadata key with the specified value. */ |
| 199 | inline void remove(const QString &key) { m_metadata.remove(key); } /*!< \brief Remove the metadata key. */ | 200 | inline void remove(const QString &key) { m_metadata.remove(key); } /*!< \brief Remove the metadata key. */ |
openbr/plugins/misc.cpp
| @@ -14,6 +14,7 @@ | @@ -14,6 +14,7 @@ | ||
| 14 | * limitations under the License. * | 14 | * limitations under the License. * |
| 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | 15 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
| 16 | 16 | ||
| 17 | +#include <QRegularExpression> | ||
| 17 | #include <opencv2/highgui/highgui.hpp> | 18 | #include <opencv2/highgui/highgui.hpp> |
| 18 | #include "openbr_internal.h" | 19 | #include "openbr_internal.h" |
| 19 | #include "openbr/core/opencvutils.h" | 20 | #include "openbr/core/opencvutils.h" |
| @@ -399,6 +400,29 @@ class AsTransform : public UntrainableMetaTransform | @@ -399,6 +400,29 @@ class AsTransform : public UntrainableMetaTransform | ||
| 399 | 400 | ||
| 400 | BR_REGISTER(Transform, AsTransform) | 401 | BR_REGISTER(Transform, AsTransform) |
| 401 | 402 | ||
| 403 | +/*! | ||
| 404 | + * \ingroup transforms | ||
| 405 | + * \brief Change the template label using a regular expresion matched to the file's base name. | ||
| 406 | + */ | ||
| 407 | +class RelabelTransform : public UntrainableMetaTransform | ||
| 408 | +{ | ||
| 409 | + Q_OBJECT | ||
| 410 | + Q_PROPERTY(QString regexp READ get_regexp WRITE set_regexp RESET reset_regexp STORED false) | ||
| 411 | + BR_PROPERTY(QString, regexp, "") | ||
| 412 | + | ||
| 413 | + void project(const Template &src, Template &dst) const | ||
| 414 | + { | ||
| 415 | + dst = src; | ||
| 416 | + QRegularExpression re(regexp); | ||
| 417 | + QRegularExpressionMatch match = re.match(dst.file.baseName()); | ||
| 418 | + if (!match.hasMatch()) | ||
| 419 | + qFatal("Unable to match regular expression \"%s\" to base name \"%s\"!", qPrintable(regexp), qPrintable(dst.file.baseName())); | ||
| 420 | + dst.file.set("Label", match.captured(match.lastCapturedIndex())); | ||
| 421 | + } | ||
| 422 | +}; | ||
| 423 | + | ||
| 424 | +BR_REGISTER(Transform, RelabelTransform) | ||
| 425 | + | ||
| 402 | } | 426 | } |
| 403 | 427 | ||
| 404 | #include "misc.moc" | 428 | #include "misc.moc" |