diff --git a/openbr/openbr_plugin.h b/openbr/openbr_plugin.h index 981f360..759b360 100644 --- a/openbr/openbr_plugin.h +++ b/openbr/openbr_plugin.h @@ -1206,7 +1206,7 @@ public: static QSharedPointer fromAlgorithm(const QString &algorithm); /*!< \brief Retrieve an algorithm's distance. */ virtual void train(const TemplateList &src) { (void) src; } /*!< \brief Train the distance. */ virtual void compare(const TemplateList &target, const TemplateList &query, Output *output) const; /*!< \brief Compare two template lists. */ - QList compare(const TemplateList &targets, const Template &query) const; /*!< \brief Compute the normalized distance between a template and a template list. */ + virtual QList compare(const TemplateList &targets, const Template &query) const; /*!< \brief Compute the normalized distance between a template and a template list. */ virtual float compare(const Template &a, const Template &b) const = 0; /*!< \brief Compute the distance between two templates. */ protected: diff --git a/openbr/plugins/draw.cpp b/openbr/plugins/draw.cpp index 9fe401f..01d816a 100644 --- a/openbr/plugins/draw.cpp +++ b/openbr/plugins/draw.cpp @@ -25,7 +25,10 @@ namespace br /*! * \ingroup transforms - * \brief Renders metadata onto the image + * \brief Renders metadata onto the image. + * + * The inPlace argument controls whether or not the image is cloned before the metadata is drawn. + * * \author Josh Klontz \cite jklontz */ class DrawTransform : public UntrainableTransform @@ -34,15 +37,17 @@ class DrawTransform : public UntrainableTransform Q_PROPERTY(bool verbose READ get_verbose WRITE set_verbose RESET reset_verbose STORED false) Q_PROPERTY(bool points READ get_points WRITE set_points RESET reset_points STORED false) Q_PROPERTY(bool rects READ get_rects WRITE set_rects RESET reset_rects STORED false) + Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false) BR_PROPERTY(bool, verbose, false) BR_PROPERTY(bool, points, true) BR_PROPERTY(bool, rects, true) + BR_PROPERTY(bool, inPlace, false) void project(const Template &src, Template &dst) const { const Scalar color(0,255,0); - const Scalar verboseColor(0, 0, 0); - dst = src.m().clone(); + const Scalar verboseColor(255, 255, 0); + dst.m() = inPlace ? src.m() : src.m().clone(); if (points) { const QList pointsList = OpenCVUtils::toPoints(src.file.namedPoints() + src.file.points()); @@ -62,13 +67,23 @@ class DrawTransform : public UntrainableTransform BR_REGISTER(Transform, DrawTransform) +/*! + * \ingroup transforms + * \brief Draw the value of the specified property at the specified point on the image + * + * The inPlace argument controls whether or not the image is cloned before it is drawn on. + * + * \author Charles Otto \cite caotto + */ class DrawPropertyPointTransform : public UntrainableTransform { Q_OBJECT Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false) Q_PROPERTY(QString pointName READ get_pointName WRITE set_pointName RESET reset_pointName STORED false) + Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false) BR_PROPERTY(QString, propName, "") BR_PROPERTY(QString, pointName, "") + BR_PROPERTY(bool, inPlace, false) void project(const Template &src, Template &dst) const @@ -77,6 +92,8 @@ class DrawPropertyPointTransform : public UntrainableTransform if (propName.isEmpty() || pointName.isEmpty()) return; + dst.m() = inPlace ? src.m() : src.m().clone(); + const Scalar textColor(255, 255, 0); QVariant prop = dst.file.value(propName); @@ -94,7 +111,9 @@ class DrawPropertyPointTransform : public UntrainableTransform QPointF targetPoint = point.toPointF(); Point2f cvPoint =OpenCVUtils::toPoint(targetPoint); - putText(dst, propString.toStdString(), cvPoint, FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1); + + std::string text = propName.toStdString() + ": " + propString.toStdString(); + putText(dst, text, cvPoint, FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1); } }; @@ -102,6 +121,65 @@ BR_REGISTER(Transform, DrawPropertyPointTransform) /*! * \ingroup transforms + * \brief Draw the values of a list of properties at the specified point on the image + * + * The inPlace argument controls whether or not the image is cloned before it is drawn on. + * + * \author Charles Otto \cite caotto + */ +class DrawPropertiesPointTransform : public UntrainableTransform +{ + Q_OBJECT + Q_PROPERTY(QStringList propNames READ get_propNames WRITE set_propNames RESET reset_propNames STORED false) + Q_PROPERTY(QString pointName READ get_pointName WRITE set_pointName RESET reset_pointName STORED false) + Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false) + BR_PROPERTY(QStringList, propNames, QStringList()) + BR_PROPERTY(QString, pointName, "") + BR_PROPERTY(bool, inPlace, false) + + void project(const Template &src, Template &dst) const + { + dst = src; + if (propNames.isEmpty() || pointName.isEmpty()) + return; + + dst.m() = inPlace ? src.m() : src.m().clone(); + + QVariant point = dst.file.value(pointName); + + if (!point.canConvert(QVariant::PointF)) + return; + + QPointF targetPoint = point.toPointF(); + + Point2f cvPoint =OpenCVUtils::toPoint(targetPoint); + + + const Scalar textColor(255, 255, 0); + + std::string outString = ""; + foreach (const QString & propName, propNames) + { + QVariant prop = dst.file.value(propName); + + if (!prop.canConvert(QVariant::String)) + continue; + QString propString = prop.toString(); + outString += propName.toStdString() + ": " + propString.toStdString() + " "; + + } + if (outString.empty()) + return; + + putText(dst, outString, cvPoint, FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1); + } + +}; +BR_REGISTER(Transform, DrawPropertiesPointTransform) + + +/*! + * \ingroup transforms * \brief Draws a grid on the image * \author Josh Klontz \cite jklontz */ diff --git a/openbr/plugins/independent.cpp b/openbr/plugins/independent.cpp index 05b6e98..462286d 100644 --- a/openbr/plugins/independent.cpp +++ b/openbr/plugins/independent.cpp @@ -73,7 +73,7 @@ static TemplateList Downsample(const TemplateList &templates, const Transform *t class IndependentTransform : public MetaTransform { Q_OBJECT - Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform STORED false) + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform STORED false) BR_PROPERTY(br::Transform*, transform, NULL) QList transforms; diff --git a/openbr/plugins/misc.cpp b/openbr/plugins/misc.cpp index 26711b2..f872f1a 100644 --- a/openbr/plugins/misc.cpp +++ b/openbr/plugins/misc.cpp @@ -469,6 +469,98 @@ class RemoveMetadataTransform : public UntrainableMetaTransform BR_REGISTER(Transform, RemoveMetadataTransform) +/*! + * \ingroup transforms + * \brief Store the last matrix of the input template as a metadata key with input property name. + * \author Charles Otto \cite caotto + */ +class SaveMatTransform : public UntrainableMetaTransform +{ + Q_OBJECT + + Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false) + BR_PROPERTY(QString, propName, "") + + void project(const Template &src, Template &dst) const + { + dst = src; + dst.file.set(propName, QVariant::fromValue(dst.m())); + } +}; +BR_REGISTER(Transform, SaveMatTransform) + +/*! + * \ingroup transforms + * \brief Set the last matrix of the input template to a matrix stored as metadata with input propName. + * + * Also removes the property from the templates metadata after restoring it. + * + * \author Charles Otto \cite caotto + */ +class RestoreMatTransform : public UntrainableMetaTransform +{ + Q_OBJECT + Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false) + BR_PROPERTY(QString, propName, "") + + void project(const Template &src, Template &dst) const + { + dst = src; + if (dst.file.contains(propName)) { + dst.clear(); + dst.m() = dst.file.get(propName); + dst.file.remove(propName); + } + } +}; +BR_REGISTER(Transform, RestoreMatTransform) + +/*! + * \ingroup transforms + * \brief Expand the width and height of a template's rects by input width and height factors. + * \author Charles Otto \cite caotto + */ +class ExpandRectTransform : public UntrainableTransform +{ + Q_OBJECT + Q_PROPERTY(float widthExpand READ get_widthExpand WRITE set_widthExpand RESET reset_widthExpand STORED false) + Q_PROPERTY(float heightExpand READ get_heightExpand WRITE set_heightExpand RESET reset_heightExpand STORED false) + BR_PROPERTY(float, widthExpand, .5) + BR_PROPERTY(float, heightExpand, .5) + void project(const Template &src, Template &dst) const + { + dst = src; + QList rects = dst.file.rects(); + for (int i=0;i < rects.size(); i++) { + QRectF rect = rects[i]; + + qreal width = rect.width(); + qreal height = rect.height(); + float half_w_expansion = widthExpand / 2; + float half_h_expansion = heightExpand / 2; + + qreal half_width = width * widthExpand; + qreal quarter_width = width * half_w_expansion; + qreal half_height = height * heightExpand; + qreal quarter_height = height * half_h_expansion; + + rect.setX(std::max(qreal(0),(rect.x() - quarter_width))); + rect.setY(std::max(qreal(0),(rect.y() - quarter_height))); + + qreal x2 = std::min(rect.width() + half_width + rect.x(), qreal(src.m().cols) - 1); + qreal y2 = std::min(rect.height() + half_height + rect.y(), qreal(src.m().rows) - 1); + + rect.setWidth(x2 - rect.x()); + rect.setHeight(y2 - rect.y()); + + rects[i] = rect; + } + dst.file.setRects(rects); + } +}; + +BR_REGISTER(Transform, ExpandRectTransform) + } #include "misc.moc" diff --git a/openbr/plugins/pp5.cpp b/openbr/plugins/pp5.cpp index d6fd9e4..e79ee92 100644 --- a/openbr/plugins/pp5.cpp +++ b/openbr/plugins/pp5.cpp @@ -213,7 +213,7 @@ struct PP5Context * \author Josh Klontz \cite jklontz * \author E. Taborsky \cite mmtaborsky */ -class PP5EnrollTransform : public UntrainableTransform +class PP5EnrollTransform : public UntrainableMetaTransform { Q_OBJECT Q_PROPERTY(bool detectOnly READ get_detectOnly WRITE set_detectOnly RESET reset_detectOnly STORED false)