Commit fc1d92b2fca6ef29b7546e7042cb993d9d564096

Authored by Scott Klum
1 parent 5d82ee4e

Procrustes transform: Fixed loading and storing or meanshape

Showing 1 changed file with 38 additions and 40 deletions
openbr/plugins/landmarks.cpp
... ... @@ -2,6 +2,7 @@
2 2 #include "openbr_internal.h"
3 3 #include "openbr/core/qtutils.h"
4 4 #include "openbr/core/opencvutils.h"
  5 +#include "openbr/core/eigenutils.h"
5 6 #include <QString>
6 7 #include <Eigen/SVD>
7 8  
... ... @@ -13,50 +14,36 @@ namespace br
13 14  
14 15 /*!
15 16 * \ingroup transforms
16   - * \brief Wraps STASM key point detector
  17 + * \brief Procrustes alignment of points
17 18 * \author Scott Klum \cite sklum
18 19 */
19 20 class ProcrustesTransform : public Transform
20 21 {
21 22 Q_OBJECT
22 23  
23   - Q_PROPERTY(QString principalShapePath READ get_principalShapePath WRITE set_principalShapePath RESET reset_principalShapePath STORED false)
24   - BR_PROPERTY(QString, principalShapePath, QString())
25   -
26 24 Eigen::MatrixXf meanShape;
27   - Mat shapeMat;
28 25  
29 26 void train(const TemplateList &data)
30 27 {
31   - QList< QList<cv::Point2f> > normalizedPoints;
  28 + QList< QList<QPointF> > normalizedPoints;
32 29  
33 30 // Normalize all sets of points
34 31 foreach (br::Template datum, data) {
35   - QList<cv::Point2f> points = OpenCVUtils::toPoints(datum.file.points());
  32 + QList<QPointF> points = datum.file.points();
36 33  
37   - if (points.empty()) {
38   - continue;
39   - }
  34 + if (points.empty()) continue;
40 35  
41   - cv::Scalar mean = cv::mean(points.toVector().toStdVector());
42   - for (int i = 0; i < points.size(); i++) {
43   - points[i].x -= mean[0];
44   - points[i].y -= mean[1];
45   - }
  36 + cv::Scalar mean = cv::mean(OpenCVUtils::toPoints(points).toVector().toStdVector());
  37 + for (int i = 0; i < points.size(); i++) points[i] -= QPointF(mean[0],mean[1]);
46 38  
47   - float norm = cv::norm(points.toVector().toStdVector());
48   - for (int i = 0; i < points.size(); i++) {
49   - points[i].x /= (norm);
50   - points[i].y /= (norm);
51   - }
  39 + float norm = cv::norm(OpenCVUtils::toPoints(points).toVector().toStdVector());
  40 + for (int i = 0; i < points.size(); i++) points[i] /= norm;
52 41  
53 42 normalizedPoints.append(points);
54 43 }
55 44  
56 45 // Determine mean shape
57   - Eigen::MatrixXf shapeTest(normalizedPoints[0].size(), 2);
58   -
59   - cv::Mat shapeBuffer(normalizedPoints[0].size(), 2, CV_32F);
  46 + Eigen::MatrixXf shapeBuffer(normalizedPoints[0].size(), 2);
60 47  
61 48 for (int i = 0; i < normalizedPoints[0].size(); i++) {
62 49  
... ... @@ -64,21 +51,18 @@ class ProcrustesTransform : public Transform
64 51 double y = 0;
65 52  
66 53 for (int j = 0; j < normalizedPoints.size(); j++) {
67   - x += normalizedPoints[j][i].x;
68   - y += normalizedPoints[j][i].y;
  54 + x += normalizedPoints[j][i].x();
  55 + y += normalizedPoints[j][i].y();
69 56 }
70 57  
71 58 x /= (double)normalizedPoints.size();
72 59 y /= (double)normalizedPoints.size();
73 60  
74   - shapeBuffer.at<float>(i,0) = x;
75   - shapeBuffer.at<float>(i,1) = y;
76   -
77   - shapeTest(i,0) = x;
78   - shapeTest(i,1) = y;
  61 + shapeBuffer(i,0) = x;
  62 + shapeBuffer(i,1) = y;
79 63 }
80 64  
81   - meanShape = shapeTest;
  65 + meanShape = shapeBuffer;
82 66 }
83 67  
84 68 void project(const Template &src, Template &dst) const
... ... @@ -86,11 +70,9 @@ class ProcrustesTransform : public Transform
86 70 QList<QPointF> points = src.file.points();
87 71  
88 72 cv::Scalar mean = cv::mean(OpenCVUtils::toPoints(points).toVector().toStdVector());
89   -
90 73 for (int i = 0; i < points.size(); i++) points[i] -= QPointF(mean[0],mean[1]);
91 74  
92 75 float norm = cv::norm(OpenCVUtils::toPoints(points).toVector().toStdVector());
93   -
94 76 Eigen::MatrixXf srcPoints(points.size(), 2);
95 77  
96 78 for (int i = 0; i < points.size(); i++) {
... ... @@ -108,7 +90,17 @@ class ProcrustesTransform : public Transform
108 90  
109 91 for (int i = 0; i < dstPoints.rows(); i++) points.append(QPointF(dstPoints(i,0),dstPoints(i,1)));
110 92  
111   - dst.file.setPoints(points);
  93 + dst.file.appendPoints(points);
  94 + }
  95 +
  96 + void store(QDataStream &stream) const
  97 + {
  98 + stream << meanShape;
  99 + }
  100 +
  101 + void load(QDataStream &stream)
  102 + {
  103 + stream >> meanShape;
112 104 }
113 105  
114 106 };
... ... @@ -133,7 +125,7 @@ class DelauneyTransform : public UntrainableTransform
133 125  
134 126 Subdiv2D subdiv(Rect(0,0,src.m().cols,src.m().rows));
135 127  
136   - foreach(const cv::Point2f& point, OpenCVUtils::toPoints(src.file.points())) subdiv.insert(point);
  128 + foreach(const cv::Point2f& point, OpenCVUtils::toPoints(src.file.points())) subdiv.insert(point);
137 129  
138 130 vector<Vec6f> triangleList;
139 131 subdiv.getTriangleList(triangleList);
... ... @@ -142,18 +134,24 @@ class DelauneyTransform : public UntrainableTransform
142 134 Scalar delaunay_color(0, 0, 0);
143 135  
144 136 if (draw) {
145   - for(size_t i = 0; i < triangleList.size(); ++i) {
  137 + int count = 0;
  138 + for(size_t i = 0; i < triangleList.size(); ++i) {
146 139 Vec6f t = triangleList[i];
147 140  
148 141 pt[0] = Point(cvRound(t[0]), cvRound(t[1]));
149 142 pt[1] = Point(cvRound(t[2]), cvRound(t[3]));
150 143 pt[2] = Point(cvRound(t[4]), cvRound(t[5]));
151   - bool outside = true;
  144 +
  145 + bool inside = true;
152 146 for (int i = 0; i < 3; i++) {
153   - if(pt[i].x > dst.m().cols || pt[i].y > dst.m().rows || pt[i].x <= 0 || pt[i].y <= 0)
154   - outside = false;
  147 + if(pt[i].x > dst.m().cols || pt[i].y > dst.m().rows || pt[i].x <= 0 || pt[i].y <= 0) {
  148 + inside = false;
  149 + }
  150 +
155 151 }
156   - if (outside) {
  152 + if (inside) {
  153 + count++;
  154 + //qDebug() << count << pt[0] << pt[1] << pt[2] << "Area" << contourArea(pt);
157 155 line(dst.m(), pt[0], pt[1], delaunay_color, 1);
158 156 line(dst.m(), pt[1], pt[2], delaunay_color, 1);
159 157 line(dst.m(), pt[2], pt[0], delaunay_color, 1);
... ...