diff --git a/openbr/plugins/algorithms.cpp b/openbr/plugins/algorithms.cpp index 39c4135..79cda08 100644 --- a/openbr/plugins/algorithms.cpp +++ b/openbr/plugins/algorithms.cpp @@ -79,6 +79,10 @@ class AlgorithmsInitializer : public Initializer Globals->abbreviations.insert("RegisterAffine", "Open+Affine(256,256,0.37,0.45)"); Globals->abbreviations.insert("ContrastEnhanced", "Open+Affine(256,256,0.37,0.45)+Cvt(Gray)+Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)"); Globals->abbreviations.insert("ColoredLBP", "Open+Affine(128,128,0.37,0.45)+Cvt(Gray)+Blur(1.1)+Gamma(0.2)+DoG(1,2)+ContrastEq(0.1,10)+LBP(1,2)+ColoredU2"); + Globals->abbreviations.insert("FlipMUCT","Flip+ReorderPoints([ 0, 1, 2, 3, 4, 5, 6, 7, 17,18,19,20,21,31,32,36,37,38,39,40,41,48,49,50,55,56,60,61,65], \ + [16,15,14,13,12,11,10, 9, 26,25,24,23,22,35,34,45,44,43,42,47,46,54,53,52,59,58,64,63,67],true)"); + Globals->abbreviations.insert("FlipMUCTNoJaw","Flip+ReorderPoints([0,1,2,3,4,14,15,19,20,21,22,23,24,31,32,33,38,39,43,44,48], \ + [9,8,7,6,5,18,17,28,27,26,25,30,29,37,36,35,42,41,47,46,50],true)"); // Transforms Globals->abbreviations.insert("FaceDetection", "Open+Cvt(Gray)+Cascade(FrontalFace)"); diff --git a/openbr/plugins/meta.cpp b/openbr/plugins/meta.cpp index 3d744d2..d831882 100644 --- a/openbr/plugins/meta.cpp +++ b/openbr/plugins/meta.cpp @@ -783,6 +783,43 @@ public: }; BR_REGISTER(Transform, DistributeTemplateTransform) +/*! + * \ingroup transforms + * \brief Generates two templates, one of which is passed through a transform and the other + * is not. No cats were harmed in the making of this transform. + * \author Scott Klum \cite sklum + */ +class SchrodingerTransform : public MetaTransform +{ + Q_OBJECT + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform) + BR_PROPERTY(br::Transform*, transform, NULL) + +public: + void train(const TemplateList &data) + { + transform->train(data); + } + + void project(const TemplateList &src, TemplateList &dst) const + { + foreach(const Template &t, src) { + dst.append(t); + Template u; + transform->project(t,u); + dst.append(u); + } + } + + void project(const Template &src, Template &dst) const { + TemplateList temp; + project(TemplateList() << src, temp); + if (!temp.isEmpty()) dst = temp.first(); + } + +}; +BR_REGISTER(Transform, SchrodingerTransform) + } // namespace br #include "meta.moc" diff --git a/openbr/plugins/regions.cpp b/openbr/plugins/regions.cpp index e6a88c8..dad3d91 100644 --- a/openbr/plugins/regions.cpp +++ b/openbr/plugins/regions.cpp @@ -242,12 +242,24 @@ class DupTransform : public UntrainableMetaTransform { Q_OBJECT Q_PROPERTY(int n READ get_n WRITE set_n RESET reset_n STORED false) + Q_PROPERTY(bool dupLandmarks READ get_dupLandmarks WRITE set_dupLandmarks RESET reset_dupLandmarks STORED false) BR_PROPERTY(int, n, 1) + BR_PROPERTY(bool, dupLandmarks, false) void project(const Template &src, Template &dst) const { for (int i=0; i points = src.file.points(); + QList rects = src.file.rects(); + + for (int i=1; i flippedPoints; + foreach(const QPointF &point, src.file.points()) { + if (axis == Y) { + flippedPoints.append(QPointF(src.m().cols-point.x(),point.y())); + } else if (axis == X) { + flippedPoints.append(QPointF(point.x(),src.m().rows-point.y())); + } else { + flippedPoints.append(QPointF(src.m().cols-point.x(),src.m().rows-point.y())); + } + } + + QList flippedRects; + foreach(const QRectF &rect, src.file.rects()) { + if (axis == Y) { + flippedRects.append(QRectF(src.m().cols-rect.right(), + rect.y(), + rect.width(), + rect.height())); + } else if (axis == X) { + flippedRects.append(QRectF(rect.x(), + src.m().rows-rect.bottom(), + rect.width(), + rect.height())); + } else { + flippedRects.append(QRectF(src.m().cols-rect.right(), + src.m().rows-rect.bottom(), + rect.width(), + rect.height())); + } + } + + dst.file.setPoints(flippedPoints); + dst.file.setRects(flippedRects); } }; - BR_REGISTER(Transform, FlipTransform) +/*! + * \ingroup transforms + * \brief Randomly rotates an image in a specified range. + * \author Scott Klum \cite sklum + */ +class RandRotateTransform : public UntrainableTransform +{ + Q_OBJECT + + Q_PROPERTY(QList range READ get_range WRITE set_range RESET reset_range STORED false) + BR_PROPERTY(QList, range, QList() << -15 << 15) + + void project(const Template &src, Template &dst) const { + int span = range.first() - range.last(); + int angle = (rand() % span) + range.first(); + Mat rotMatrix = getRotationMatrix2D(Point2f(src.m().rows/2,src.m().cols/2),angle,1.0); + warpAffine(src,dst,rotMatrix,Size(src.m().cols,src.m().rows)); + + QList points = src.file.points(); + QList rotatedPoints; + for (int i=0; i(0,0)+ + points.at(i).y()*rotMatrix.at(0,1)+ + rotMatrix.at(0,2), + points.at(i).x()*rotMatrix.at(1,0)+ + points.at(i).y()*rotMatrix.at(1,1)+ + rotMatrix.at(1,2))); + } + + dst.file.setPoints(rotatedPoints); + } +}; + +BR_REGISTER(Transform, RandRotateTransform) + } // namespace br #include "register.moc" diff --git a/openbr/plugins/template.cpp b/openbr/plugins/template.cpp index b771c4f..5c57d81 100644 --- a/openbr/plugins/template.cpp +++ b/openbr/plugins/template.cpp @@ -207,6 +207,41 @@ public: BR_REGISTER(Transform, FilterDupeMetadataTransform) +/*! + * \ingroup transforms + * \brief Reorder the points such that points[from[i]] becomes points[to[i]] and + * vice versa + * \author Scott Klum \cite sklum + */ +class ReorderPointsTransform : public UntrainableMetadataTransform +{ + Q_OBJECT + + Q_PROPERTY(QList from READ get_from WRITE set_from RESET reset_from STORED false) + Q_PROPERTY(QList to READ get_to WRITE set_to RESET reset_to STORED false) + Q_PROPERTY(bool flippedOnly READ get_flippedOnly WRITE set_flippedOnly RESET reset_flippedOnly STORED false) + BR_PROPERTY(QList, from, QList()) + BR_PROPERTY(QList, to, QList()) + BR_PROPERTY(bool, flippedOnly, false) + + void projectMetadata(const File &src, File &dst) const + { + if (flippedOnly && !src.contains("Flipped")) { + dst = src; + return; + } + + if (from.size() == to.size()) { + QList points = src.points(); + for (int i=0; i