diff --git a/openbr/openbr_plugin.cpp b/openbr/openbr_plugin.cpp index 91cecc6..44c94a3 100644 --- a/openbr/openbr_plugin.cpp +++ b/openbr/openbr_plugin.cpp @@ -166,10 +166,10 @@ QVariant File::parse(const QString &value) void File::set(const QString &key, const QString &value) { if (value.startsWith('[') && value.endsWith(']')) { - QList variants; + QVariantList variants; foreach (const QString &value, QtUtils::parse(value.mid(1, value.size()-2))) variants.append(parse(value)); - set(key, QVariant(variants)); + set(key, variants); } else { set(key, QVariant(parse(value))); } @@ -806,9 +806,7 @@ void Object::setProperty(const QString &name, QVariant value) value = v; } else if ((type.startsWith("QList<") && type.endsWith(">")) || (type == "QStringList") || (type == "QVariantList")) { QVariantList elements; - if (value.canConvert()) { - elements = value.value(); - } else if (value.canConvert< QList >()) { + if (value.canConvert< QList >()) { foreach (Transform *transform, value.value< QList >()) elements.append(QVariant::fromValue(transform)); } else if (value.canConvert()) { @@ -817,6 +815,8 @@ void Object::setProperty(const QString &name, QVariant value) qFatal("Expected a list to start with '[' and end with 'brackets']'."); foreach (const QString &element, parse(string.mid(1, string.size()-2))) elements.append(element); + } else if (value.canConvert()) { + elements = value.value(); } else { qFatal("Expected a list."); } @@ -825,8 +825,19 @@ void Object::setProperty(const QString &name, QVariant value) value.setValue(elements); } else if ((type == "QList") || (type == "QStringList")) { QStringList parsedValues; - foreach (const QVariant &element, elements) - parsedValues.append(element.toString()); + foreach (const QVariant &element, elements) { + if (element.canConvert()) { + parsedValues.append(element.toString()); + } else if (element.canConvert()) { + const QPointF point = element.toPointF(); + parsedValues.push_back(QString("(%1,%2)").arg(QString::number(point.x()), QString::number(point.y()))); + } else if (element.canConvert()) { + const QRectF rect = element.toRectF(); + parsedValues.push_back(QString("(%1,%2,%3,%4)").arg(QString::number(rect.x()), QString::number(rect.y()), QString::number(rect.width()), QString::number(rect.height()))); + } else { + qFatal("Can't convert variant to string."); + } + } value.setValue(parsedValues); } else if (type == "QList") { QList parsedValues; bool ok; diff --git a/openbr/plugins/stasm4.cpp b/openbr/plugins/stasm4.cpp index 62c9f8e..63c5a11 100644 --- a/openbr/plugins/stasm4.cpp +++ b/openbr/plugins/stasm4.cpp @@ -64,8 +64,10 @@ class StasmTransform : public UntrainableTransform BR_PROPERTY(bool, stasm3Format, false) Q_PROPERTY(bool clearLandmarks READ get_clearLandmarks WRITE set_clearLandmarks RESET reset_clearLandmarks STORED false) BR_PROPERTY(bool, clearLandmarks, false) - Q_PROPERTY(QVariantList pinEyes READ get_pinEyes WRITE set_pinEyes RESET reset_pinEyes STORED false) - BR_PROPERTY(QVariantList, pinEyes, QVariantList()) + Q_PROPERTY(QList pinPoints READ get_pinPoints WRITE set_pinPoints RESET reset_pinPoints STORED false) + BR_PROPERTY(QList, pinPoints, QList()) + Q_PROPERTY(QStringList pinLabels READ get_pinLabels WRITE set_pinLabels RESET reset_pinLabels STORED false) + BR_PROPERTY(QStringList, pinLabels, QStringList()) Resource stasmCascadeResource; @@ -91,51 +93,42 @@ class StasmTransform : public UntrainableTransform int nLandmarks = stasm_NLANDMARKS; float landmarks[2 * stasm_NLANDMARKS]; - if (!pinEyes.isEmpty()) { - // Two use cases are accounted for: - // 1. Pin eyes without normalization: in this case the string list should contain the KEYS for right then left eyes, respectively. - // 2. Pin eyes with normalization: in this case the string list should contain the COORDINATES of the right then left eyes, respectively. - // If both cases fail, we default to stasm_search_single. - - bool ok = false; - QPointF rightEye; - QPointF leftEye; - - QString r = pinEyes.at(0).toString(); - QString l = pinEyes.at(1).toString(); - - if (src.file.contains("Affine_0") && src.file.contains("Affine_1")) { - rightEye = QtUtils::toPoint(r); - leftEye = QtUtils::toPoint(l); - if (!rightEye.isNull() && !leftEye.isNull()) - ok = true; - } + bool searchPinned = false; + + QPointF rightEye, leftEye; + /* Two use cases are accounted for: + * 1. Pin eyes without normalization: in this case the string list should contain the KEYS for right then left eyes, respectively. + * 2. Pin eyes with normalization: in this case the string list should contain the COORDINATES of the right then left eyes, respectively. + * Currently, we only support normalization with a transformation such that the src file contains Affine_0 and Affine_1. Checking for + * these keys prevents us from pinning eyes on a face that wasn't actually transformed (see AffineTransform). + * If both cases fail, we default to stasm_search_single. */ + + if (!pinPoints.isEmpty() && src.file.contains("Affine_0") && src.file.contains("Affine_1")) { + rightEye = QPointF(pinPoints.at(0), pinPoints.at(1)); + leftEye = QPointF(pinPoints.at(2), pinPoints.at(3)); + searchPinned = true; + } else if (!pinLabels.isEmpty()) { + rightEye = src.file.get(pinLabels.at(0), QPointF()); + leftEye = src.file.get(pinLabels.at(1), QPointF()); + searchPinned = true; + } + + if (searchPinned) { + float pins[2 * stasm_NLANDMARKS]; - if (!ok) { - if (!r.isNull() && !l.isNull() && src.file.contains(r) && src.file.contains(l)) - { - rightEye = src.file.get(r, QPointF()); - leftEye = src.file.get(l, QPointF()); - ok = true; - } + for (int i = 0; i < nLandmarks; i++) { + if (i == 38) /*Stasm Right Eye*/ { pins[2*i] = rightEye.x(); pins[2*i+1] = rightEye.y(); } + else if (i == 39) /*Stasm Left Eye*/ { pins[2*i] = leftEye.x(); pins[2*i+1] = leftEye.y(); } + else { pins[2*i] = 0; pins[2*i+1] = 0; } } - float eyes[2 * stasm_NLANDMARKS]; + stasm_search_pinned(landmarks, pins, reinterpret_cast(stasmSrc.data), stasmSrc.cols, stasmSrc.rows, NULL); - if (ok) { - for (int i = 0; i < nLandmarks; i++) { - if (i == 38) /*Stasm Right Eye*/ { eyes[2*i] = rightEye.x(); eyes[2*i+1] = rightEye.y(); } - else if (i == 39) /*Stasm Left Eye*/ { eyes[2*i] = leftEye.x(); eyes[2*i+1] = leftEye.y(); } - else { eyes[2*i] = 0; eyes[2*i+1] = 0; } - } - stasm_search_pinned(landmarks, eyes, reinterpret_cast(src.m().data), src.m().cols, src.m().rows, NULL); - - // The ASM in Stasm is guaranteed to converge in this case - foundFace = 1; - } + // The ASM in Stasm is guaranteed to converge in this case + foundFace = 1; } - if (!foundFace) stasm_search_single(&foundFace, landmarks, reinterpret_cast(src.m().data), src.m().cols, src.m().rows, *stasmCascade, NULL, NULL); + if (!foundFace) stasm_search_single(&foundFace, landmarks, reinterpret_cast(stasmSrc.data), stasmSrc.cols, stasmSrc.rows, *stasmCascade, NULL, NULL); if (stasm3Format) { nLandmarks = 76;