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,6 +2,7 @@
2 #include "openbr_internal.h" 2 #include "openbr_internal.h"
3 #include "openbr/core/qtutils.h" 3 #include "openbr/core/qtutils.h"
4 #include "openbr/core/opencvutils.h" 4 #include "openbr/core/opencvutils.h"
  5 +#include "openbr/core/eigenutils.h"
5 #include <QString> 6 #include <QString>
6 #include <Eigen/SVD> 7 #include <Eigen/SVD>
7 8
@@ -13,50 +14,36 @@ namespace br @@ -13,50 +14,36 @@ namespace br
13 14
14 /*! 15 /*!
15 * \ingroup transforms 16 * \ingroup transforms
16 - * \brief Wraps STASM key point detector 17 + * \brief Procrustes alignment of points
17 * \author Scott Klum \cite sklum 18 * \author Scott Klum \cite sklum
18 */ 19 */
19 class ProcrustesTransform : public Transform 20 class ProcrustesTransform : public Transform
20 { 21 {
21 Q_OBJECT 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 Eigen::MatrixXf meanShape; 24 Eigen::MatrixXf meanShape;
27 - Mat shapeMat;  
28 25
29 void train(const TemplateList &data) 26 void train(const TemplateList &data)
30 { 27 {
31 - QList< QList<cv::Point2f> > normalizedPoints; 28 + QList< QList<QPointF> > normalizedPoints;
32 29
33 // Normalize all sets of points 30 // Normalize all sets of points
34 foreach (br::Template datum, data) { 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 normalizedPoints.append(points); 42 normalizedPoints.append(points);
54 } 43 }
55 44
56 // Determine mean shape 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 for (int i = 0; i < normalizedPoints[0].size(); i++) { 48 for (int i = 0; i < normalizedPoints[0].size(); i++) {
62 49
@@ -64,21 +51,18 @@ class ProcrustesTransform : public Transform @@ -64,21 +51,18 @@ class ProcrustesTransform : public Transform
64 double y = 0; 51 double y = 0;
65 52
66 for (int j = 0; j < normalizedPoints.size(); j++) { 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 x /= (double)normalizedPoints.size(); 58 x /= (double)normalizedPoints.size();
72 y /= (double)normalizedPoints.size(); 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 void project(const Template &src, Template &dst) const 68 void project(const Template &src, Template &dst) const
@@ -86,11 +70,9 @@ class ProcrustesTransform : public Transform @@ -86,11 +70,9 @@ class ProcrustesTransform : public Transform
86 QList<QPointF> points = src.file.points(); 70 QList<QPointF> points = src.file.points();
87 71
88 cv::Scalar mean = cv::mean(OpenCVUtils::toPoints(points).toVector().toStdVector()); 72 cv::Scalar mean = cv::mean(OpenCVUtils::toPoints(points).toVector().toStdVector());
89 -  
90 for (int i = 0; i < points.size(); i++) points[i] -= QPointF(mean[0],mean[1]); 73 for (int i = 0; i < points.size(); i++) points[i] -= QPointF(mean[0],mean[1]);
91 74
92 float norm = cv::norm(OpenCVUtils::toPoints(points).toVector().toStdVector()); 75 float norm = cv::norm(OpenCVUtils::toPoints(points).toVector().toStdVector());
93 -  
94 Eigen::MatrixXf srcPoints(points.size(), 2); 76 Eigen::MatrixXf srcPoints(points.size(), 2);
95 77
96 for (int i = 0; i < points.size(); i++) { 78 for (int i = 0; i < points.size(); i++) {
@@ -108,7 +90,17 @@ class ProcrustesTransform : public Transform @@ -108,7 +90,17 @@ class ProcrustesTransform : public Transform
108 90
109 for (int i = 0; i < dstPoints.rows(); i++) points.append(QPointF(dstPoints(i,0),dstPoints(i,1))); 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,7 +125,7 @@ class DelauneyTransform : public UntrainableTransform
133 125
134 Subdiv2D subdiv(Rect(0,0,src.m().cols,src.m().rows)); 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 vector<Vec6f> triangleList; 130 vector<Vec6f> triangleList;
139 subdiv.getTriangleList(triangleList); 131 subdiv.getTriangleList(triangleList);
@@ -142,18 +134,24 @@ class DelauneyTransform : public UntrainableTransform @@ -142,18 +134,24 @@ class DelauneyTransform : public UntrainableTransform
142 Scalar delaunay_color(0, 0, 0); 134 Scalar delaunay_color(0, 0, 0);
143 135
144 if (draw) { 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 Vec6f t = triangleList[i]; 139 Vec6f t = triangleList[i];
147 140
148 pt[0] = Point(cvRound(t[0]), cvRound(t[1])); 141 pt[0] = Point(cvRound(t[0]), cvRound(t[1]));
149 pt[1] = Point(cvRound(t[2]), cvRound(t[3])); 142 pt[1] = Point(cvRound(t[2]), cvRound(t[3]));
150 pt[2] = Point(cvRound(t[4]), cvRound(t[5])); 143 pt[2] = Point(cvRound(t[4]), cvRound(t[5]));
151 - bool outside = true; 144 +
  145 + bool inside = true;
152 for (int i = 0; i < 3; i++) { 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 line(dst.m(), pt[0], pt[1], delaunay_color, 1); 155 line(dst.m(), pt[0], pt[1], delaunay_color, 1);
158 line(dst.m(), pt[1], pt[2], delaunay_color, 1); 156 line(dst.m(), pt[1], pt[2], delaunay_color, 1);
159 line(dst.m(), pt[2], pt[0], delaunay_color, 1); 157 line(dst.m(), pt[2], pt[0], delaunay_color, 1);