Commit 7195a8fae486f5348b1c9da0e496e797b8d9d047
1 parent
bc2d76c0
Add an option to draw on images without cloning them
Add an inPlace argument to draw, and add a couple transforms for drawing the values of properties at some named point on an image. The inPlace argument (default false) controls whether or not an image is cloned before it is drawn on. Not cloning the image means the transforms doesn't exactly obey the const modifier on the input template (since it alters the values pointed at by that matrix), which could lead to unexpected results in some scenarios. On the other hand, the clone operation is wasteful in some cases, and also not cloning can be useful in scenarios such as drawing a set of detections represented by different templates on the same image, so as a compromise we have a default off option to draw in place.
Showing
1 changed file
with
81 additions
and
3 deletions
openbr/plugins/draw.cpp
| @@ -25,7 +25,10 @@ namespace br | @@ -25,7 +25,10 @@ namespace br | ||
| 25 | 25 | ||
| 26 | /*! | 26 | /*! |
| 27 | * \ingroup transforms | 27 | * \ingroup transforms |
| 28 | - * \brief Renders metadata onto the image | 28 | + * \brief Renders metadata onto the image. |
| 29 | + * | ||
| 30 | + * The inPlace argument controls whether or not the image is cloned before the metadata is drawn. | ||
| 31 | + * | ||
| 29 | * \author Josh Klontz \cite jklontz | 32 | * \author Josh Klontz \cite jklontz |
| 30 | */ | 33 | */ |
| 31 | class DrawTransform : public UntrainableTransform | 34 | class DrawTransform : public UntrainableTransform |
| @@ -34,15 +37,17 @@ class DrawTransform : public UntrainableTransform | @@ -34,15 +37,17 @@ class DrawTransform : public UntrainableTransform | ||
| 34 | Q_PROPERTY(bool verbose READ get_verbose WRITE set_verbose RESET reset_verbose STORED false) | 37 | Q_PROPERTY(bool verbose READ get_verbose WRITE set_verbose RESET reset_verbose STORED false) |
| 35 | Q_PROPERTY(bool points READ get_points WRITE set_points RESET reset_points STORED false) | 38 | Q_PROPERTY(bool points READ get_points WRITE set_points RESET reset_points STORED false) |
| 36 | Q_PROPERTY(bool rects READ get_rects WRITE set_rects RESET reset_rects STORED false) | 39 | Q_PROPERTY(bool rects READ get_rects WRITE set_rects RESET reset_rects STORED false) |
| 40 | + Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false) | ||
| 37 | BR_PROPERTY(bool, verbose, false) | 41 | BR_PROPERTY(bool, verbose, false) |
| 38 | BR_PROPERTY(bool, points, true) | 42 | BR_PROPERTY(bool, points, true) |
| 39 | BR_PROPERTY(bool, rects, true) | 43 | BR_PROPERTY(bool, rects, true) |
| 44 | + BR_PROPERTY(bool, inPlace, false) | ||
| 40 | 45 | ||
| 41 | void project(const Template &src, Template &dst) const | 46 | void project(const Template &src, Template &dst) const |
| 42 | { | 47 | { |
| 43 | const Scalar color(0,255,0); | 48 | const Scalar color(0,255,0); |
| 44 | const Scalar verboseColor(255, 255, 0); | 49 | const Scalar verboseColor(255, 255, 0); |
| 45 | - dst = src.m().clone(); | 50 | + dst.m() = inPlace ? src.m() : src.m().clone(); |
| 46 | 51 | ||
| 47 | if (points) { | 52 | if (points) { |
| 48 | const QList<Point2f> pointsList = OpenCVUtils::toPoints(src.file.namedPoints() + src.file.points()); | 53 | const QList<Point2f> pointsList = OpenCVUtils::toPoints(src.file.namedPoints() + src.file.points()); |
| @@ -62,13 +67,23 @@ class DrawTransform : public UntrainableTransform | @@ -62,13 +67,23 @@ class DrawTransform : public UntrainableTransform | ||
| 62 | BR_REGISTER(Transform, DrawTransform) | 67 | BR_REGISTER(Transform, DrawTransform) |
| 63 | 68 | ||
| 64 | 69 | ||
| 70 | +/*! | ||
| 71 | + * \ingroup transforms | ||
| 72 | + * \brief Draw the value of the specified property at the specified point on the image | ||
| 73 | + * | ||
| 74 | + * The inPlace argument controls whether or not the image is cloned before it is drawn on. | ||
| 75 | + * | ||
| 76 | + * \author Charles Otto \cite caotto | ||
| 77 | + */ | ||
| 65 | class DrawPropertyPointTransform : public UntrainableTransform | 78 | class DrawPropertyPointTransform : public UntrainableTransform |
| 66 | { | 79 | { |
| 67 | Q_OBJECT | 80 | Q_OBJECT |
| 68 | Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false) | 81 | Q_PROPERTY(QString propName READ get_propName WRITE set_propName RESET reset_propName STORED false) |
| 69 | Q_PROPERTY(QString pointName READ get_pointName WRITE set_pointName RESET reset_pointName STORED false) | 82 | Q_PROPERTY(QString pointName READ get_pointName WRITE set_pointName RESET reset_pointName STORED false) |
| 83 | + Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false) | ||
| 70 | BR_PROPERTY(QString, propName, "") | 84 | BR_PROPERTY(QString, propName, "") |
| 71 | BR_PROPERTY(QString, pointName, "") | 85 | BR_PROPERTY(QString, pointName, "") |
| 86 | + BR_PROPERTY(bool, inPlace, false) | ||
| 72 | 87 | ||
| 73 | 88 | ||
| 74 | void project(const Template &src, Template &dst) const | 89 | void project(const Template &src, Template &dst) const |
| @@ -77,6 +92,8 @@ class DrawPropertyPointTransform : public UntrainableTransform | @@ -77,6 +92,8 @@ class DrawPropertyPointTransform : public UntrainableTransform | ||
| 77 | if (propName.isEmpty() || pointName.isEmpty()) | 92 | if (propName.isEmpty() || pointName.isEmpty()) |
| 78 | return; | 93 | return; |
| 79 | 94 | ||
| 95 | + dst.m() = inPlace ? src.m() : src.m().clone(); | ||
| 96 | + | ||
| 80 | const Scalar textColor(255, 255, 0); | 97 | const Scalar textColor(255, 255, 0); |
| 81 | 98 | ||
| 82 | QVariant prop = dst.file.value(propName); | 99 | QVariant prop = dst.file.value(propName); |
| @@ -94,7 +111,9 @@ class DrawPropertyPointTransform : public UntrainableTransform | @@ -94,7 +111,9 @@ class DrawPropertyPointTransform : public UntrainableTransform | ||
| 94 | QPointF targetPoint = point.toPointF(); | 111 | QPointF targetPoint = point.toPointF(); |
| 95 | 112 | ||
| 96 | Point2f cvPoint =OpenCVUtils::toPoint(targetPoint); | 113 | Point2f cvPoint =OpenCVUtils::toPoint(targetPoint); |
| 97 | - putText(dst, propString.toStdString(), cvPoint, FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1); | 114 | + |
| 115 | + std::string text = propName.toStdString() + ": " + propString.toStdString(); | ||
| 116 | + putText(dst, text, cvPoint, FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1); | ||
| 98 | } | 117 | } |
| 99 | 118 | ||
| 100 | }; | 119 | }; |
| @@ -102,6 +121,65 @@ BR_REGISTER(Transform, DrawPropertyPointTransform) | @@ -102,6 +121,65 @@ BR_REGISTER(Transform, DrawPropertyPointTransform) | ||
| 102 | 121 | ||
| 103 | /*! | 122 | /*! |
| 104 | * \ingroup transforms | 123 | * \ingroup transforms |
| 124 | + * \brief Draw the values of a list of properties at the specified point on the image | ||
| 125 | + * | ||
| 126 | + * The inPlace argument controls whether or not the image is cloned before it is drawn on. | ||
| 127 | + * | ||
| 128 | + * \author Charles Otto \cite caotto | ||
| 129 | + */ | ||
| 130 | +class DrawPropertiesPointTransform : public UntrainableTransform | ||
| 131 | +{ | ||
| 132 | + Q_OBJECT | ||
| 133 | + Q_PROPERTY(QStringList propNames READ get_propNames WRITE set_propNames RESET reset_propNames STORED false) | ||
| 134 | + Q_PROPERTY(QString pointName READ get_pointName WRITE set_pointName RESET reset_pointName STORED false) | ||
| 135 | + Q_PROPERTY(bool inPlace READ get_inPlace WRITE set_inPlace RESET reset_inPlace STORED false) | ||
| 136 | + BR_PROPERTY(QStringList, propNames, QStringList()) | ||
| 137 | + BR_PROPERTY(QString, pointName, "") | ||
| 138 | + BR_PROPERTY(bool, inPlace, false) | ||
| 139 | + | ||
| 140 | + void project(const Template &src, Template &dst) const | ||
| 141 | + { | ||
| 142 | + dst = src; | ||
| 143 | + if (propNames.isEmpty() || pointName.isEmpty()) | ||
| 144 | + return; | ||
| 145 | + | ||
| 146 | + dst.m() = inPlace ? src.m() : src.m().clone(); | ||
| 147 | + | ||
| 148 | + QVariant point = dst.file.value(pointName); | ||
| 149 | + | ||
| 150 | + if (!point.canConvert(QVariant::PointF)) | ||
| 151 | + return; | ||
| 152 | + | ||
| 153 | + QPointF targetPoint = point.toPointF(); | ||
| 154 | + | ||
| 155 | + Point2f cvPoint =OpenCVUtils::toPoint(targetPoint); | ||
| 156 | + | ||
| 157 | + | ||
| 158 | + const Scalar textColor(255, 255, 0); | ||
| 159 | + | ||
| 160 | + std::string outString = ""; | ||
| 161 | + foreach (const QString & propName, propNames) | ||
| 162 | + { | ||
| 163 | + QVariant prop = dst.file.value(propName); | ||
| 164 | + | ||
| 165 | + if (!prop.canConvert(QVariant::String)) | ||
| 166 | + continue; | ||
| 167 | + QString propString = prop.toString(); | ||
| 168 | + outString += propName.toStdString() + ": " + propString.toStdString() + " "; | ||
| 169 | + | ||
| 170 | + } | ||
| 171 | + if (outString.empty()) | ||
| 172 | + return; | ||
| 173 | + | ||
| 174 | + putText(dst, outString, cvPoint, FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1); | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | +}; | ||
| 178 | +BR_REGISTER(Transform, DrawPropertiesPointTransform) | ||
| 179 | + | ||
| 180 | + | ||
| 181 | +/*! | ||
| 182 | + * \ingroup transforms | ||
| 105 | * \brief Draws a grid on the image | 183 | * \brief Draws a grid on the image |
| 106 | * \author Josh Klontz \cite jklontz | 184 | * \author Josh Klontz \cite jklontz |
| 107 | */ | 185 | */ |