Commit 5d82ee4ecf58e65cdbf5eb0fd008f993b894978e

Authored by Scott Klum
1 parent 66160b30

Delauney transform: started; Procrusted transform: suboptimal, but functionally done

openbr/plugins/landmarks.cpp 0 → 100644
  1 +#include <opencv2/opencv.hpp>
  2 +#include "openbr_internal.h"
  3 +#include "openbr/core/qtutils.h"
  4 +#include "openbr/core/opencvutils.h"
  5 +#include <QString>
  6 +#include <Eigen/SVD>
  7 +
  8 +using namespace std;
  9 +using namespace cv;
  10 +
  11 +namespace br
  12 +{
  13 +
  14 +/*!
  15 + * \ingroup transforms
  16 + * \brief Wraps STASM key point detector
  17 + * \author Scott Klum \cite sklum
  18 + */
  19 +class ProcrustesTransform : public Transform
  20 +{
  21 + Q_OBJECT
  22 +
  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;
  27 + Mat shapeMat;
  28 +
  29 + void train(const TemplateList &data)
  30 + {
  31 + QList< QList<cv::Point2f> > normalizedPoints;
  32 +
  33 + // Normalize all sets of points
  34 + foreach (br::Template datum, data) {
  35 + QList<cv::Point2f> points = OpenCVUtils::toPoints(datum.file.points());
  36 +
  37 + if (points.empty()) {
  38 + continue;
  39 + }
  40 +
  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 + }
  46 +
  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 + }
  52 +
  53 + normalizedPoints.append(points);
  54 + }
  55 +
  56 + // Determine mean shape
  57 + Eigen::MatrixXf shapeTest(normalizedPoints[0].size(), 2);
  58 +
  59 + cv::Mat shapeBuffer(normalizedPoints[0].size(), 2, CV_32F);
  60 +
  61 + for (int i = 0; i < normalizedPoints[0].size(); i++) {
  62 +
  63 + double x = 0;
  64 + double y = 0;
  65 +
  66 + for (int j = 0; j < normalizedPoints.size(); j++) {
  67 + x += normalizedPoints[j][i].x;
  68 + y += normalizedPoints[j][i].y;
  69 + }
  70 +
  71 + x /= (double)normalizedPoints.size();
  72 + y /= (double)normalizedPoints.size();
  73 +
  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;
  79 + }
  80 +
  81 + meanShape = shapeTest;
  82 + }
  83 +
  84 + void project(const Template &src, Template &dst) const
  85 + {
  86 + QList<QPointF> points = src.file.points();
  87 +
  88 + 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]);
  91 +
  92 + float norm = cv::norm(OpenCVUtils::toPoints(points).toVector().toStdVector());
  93 +
  94 + Eigen::MatrixXf srcPoints(points.size(), 2);
  95 +
  96 + for (int i = 0; i < points.size(); i++) {
  97 + srcPoints(i,0) = points[i].x()/(norm/150.)+50;
  98 + srcPoints(i,1) = points[i].y()/(norm/150.)+50;
  99 + }
  100 +
  101 + Eigen::JacobiSVD<Eigen::MatrixXf> svd(srcPoints.transpose()*meanShape, Eigen::ComputeThinU | Eigen::ComputeThinV);
  102 +
  103 + Eigen::MatrixXf R = svd.matrixU()*svd.matrixV().transpose();
  104 +
  105 + Eigen::MatrixXf dstPoints = srcPoints*R;
  106 +
  107 + points.clear();
  108 +
  109 + for (int i = 0; i < dstPoints.rows(); i++) points.append(QPointF(dstPoints(i,0),dstPoints(i,1)));
  110 +
  111 + dst.file.setPoints(points);
  112 + }
  113 +
  114 +};
  115 +
  116 +BR_REGISTER(Transform, ProcrustesTransform)
  117 +
  118 +/*!
  119 + * \ingroup transforms
  120 + * \brief Wraps STASM key point detector
  121 + * \author Scott Klum \cite sklum
  122 + */
  123 +class DelauneyTransform : public UntrainableTransform
  124 +{
  125 + Q_OBJECT
  126 +
  127 + Q_PROPERTY(bool draw READ get_draw WRITE set_draw RESET reset_draw STORED false)
  128 + BR_PROPERTY(bool, draw, false)
  129 +
  130 + void project(const Template &src, Template &dst) const
  131 + {
  132 + dst = src;
  133 +
  134 + Subdiv2D subdiv(Rect(0,0,src.m().cols,src.m().rows));
  135 +
  136 + foreach(const cv::Point2f& point, OpenCVUtils::toPoints(src.file.points())) subdiv.insert(point);
  137 +
  138 + vector<Vec6f> triangleList;
  139 + subdiv.getTriangleList(triangleList);
  140 + vector<Point> pt(3);
  141 +
  142 + Scalar delaunay_color(0, 0, 0);
  143 +
  144 + if (draw) {
  145 + for(size_t i = 0; i < triangleList.size(); ++i) {
  146 + Vec6f t = triangleList[i];
  147 +
  148 + pt[0] = Point(cvRound(t[0]), cvRound(t[1]));
  149 + pt[1] = Point(cvRound(t[2]), cvRound(t[3]));
  150 + pt[2] = Point(cvRound(t[4]), cvRound(t[5]));
  151 + bool outside = true;
  152 + 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;
  155 + }
  156 + if (outside) {
  157 + line(dst.m(), pt[0], pt[1], delaunay_color, 1);
  158 + line(dst.m(), pt[1], pt[2], delaunay_color, 1);
  159 + line(dst.m(), pt[2], pt[0], delaunay_color, 1);
  160 + }
  161 + }
  162 + }
  163 + }
  164 +
  165 +};
  166 +
  167 +BR_REGISTER(Transform, DelauneyTransform)
  168 +
  169 +} // namespace br
  170 +
  171 +#include "landmarks.moc"
openbr/plugins/regions.cpp
@@ -201,7 +201,7 @@ class RectFromPointsTransform : public UntrainableTransform @@ -201,7 +201,7 @@ class RectFromPointsTransform : public UntrainableTransform
201 Q_PROPERTY(QList<int> indices READ get_indices WRITE set_indices RESET reset_indices STORED false) 201 Q_PROPERTY(QList<int> indices READ get_indices WRITE set_indices RESET reset_indices STORED false)
202 Q_PROPERTY(double padding READ get_padding WRITE set_padding RESET reset_padding STORED false) 202 Q_PROPERTY(double padding READ get_padding WRITE set_padding RESET reset_padding STORED false)
203 Q_PROPERTY(double aspectRatio READ get_aspectRatio WRITE set_aspectRatio RESET reset_aspectRatio STORED false) 203 Q_PROPERTY(double aspectRatio READ get_aspectRatio WRITE set_aspectRatio RESET reset_aspectRatio STORED false)
204 - Q_PROPERTY(bool crop READ get_crop WRITE set_crop RESET reset_crop STORED false); 204 + Q_PROPERTY(bool crop READ get_crop WRITE set_crop RESET reset_crop STORED false)
205 BR_PROPERTY(QList<int>, indices, QList<int>()) 205 BR_PROPERTY(QList<int>, indices, QList<int>())
206 BR_PROPERTY(double, padding, 0) 206 BR_PROPERTY(double, padding, 0)
207 BR_PROPERTY(double, aspectRatio, 1.0) 207 BR_PROPERTY(double, aspectRatio, 1.0)
@@ -220,13 +220,15 @@ class RectFromPointsTransform : public UntrainableTransform @@ -220,13 +220,15 @@ class RectFromPointsTransform : public UntrainableTransform
220 int maxX, maxY; 220 int maxX, maxY;
221 maxX = maxY = -std::numeric_limits<int>::max(); 221 maxX = maxY = -std::numeric_limits<int>::max();
222 222
  223 + QList<QPointF> points;
  224 +
223 foreach(int index, indices) { 225 foreach(int index, indices) {
224 if (src.file.points().size() > index) { 226 if (src.file.points().size() > index) {
225 if (src.file.points()[index].x() < minX) minX = src.file.points()[index].x(); 227 if (src.file.points()[index].x() < minX) minX = src.file.points()[index].x();
226 if (src.file.points()[index].x() > maxX) maxX = src.file.points()[index].x(); 228 if (src.file.points()[index].x() > maxX) maxX = src.file.points()[index].x();
227 if (src.file.points()[index].y() < minY) minY = src.file.points()[index].y(); 229 if (src.file.points()[index].y() < minY) minY = src.file.points()[index].y();
228 if (src.file.points()[index].y() > maxY) maxY = src.file.points()[index].y(); 230 if (src.file.points()[index].y() > maxY) maxY = src.file.points()[index].y();
229 - dst.file.appendPoint(src.file.points()[index]); 231 + points.append(src.file.points()[index]);
230 } 232 }
231 } 233 }
232 234
@@ -238,6 +240,8 @@ class RectFromPointsTransform : public UntrainableTransform @@ -238,6 +240,8 @@ class RectFromPointsTransform : public UntrainableTransform
238 double deltaHeight = width/aspectRatio - height; 240 double deltaHeight = width/aspectRatio - height;
239 height += deltaHeight; 241 height += deltaHeight;
240 242
  243 + dst.file.setPoints(points);
  244 +
241 if (crop) dst.m() = src.m()(Rect(std::max(0.0, minX - deltaWidth/2.0), std::max(0.0, minY - deltaHeight/2.0), std::min((double)src.m().cols, width), std::min((double)src.m().rows, height))); 245 if (crop) dst.m() = src.m()(Rect(std::max(0.0, minX - deltaWidth/2.0), std::max(0.0, minY - deltaHeight/2.0), std::min((double)src.m().cols, width), std::min((double)src.m().rows, height)));
242 else dst.m() = src.m(); 246 else dst.m() = src.m();
243 } 247 }
openbr/plugins/stasm4.cpp
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 #include <QString> 7 #include <QString>
8 #include <Eigen/SVD> 8 #include <Eigen/SVD>
9 9
  10 +using namespace std;
10 using namespace cv; 11 using namespace cv;
11 12
12 namespace br 13 namespace br
@@ -83,109 +84,6 @@ class StasmTransform : public UntrainableTransform @@ -83,109 +84,6 @@ class StasmTransform : public UntrainableTransform
83 84
84 BR_REGISTER(Transform, StasmTransform) 85 BR_REGISTER(Transform, StasmTransform)
85 86
86 -#include <iostream>  
87 -  
88 -/*!  
89 - * \ingroup transforms  
90 - * \brief Wraps STASM key point detector  
91 - * \author Scott Klum \cite sklum  
92 - */  
93 -class ProcrustesTransform : public Transform  
94 -{  
95 - Q_OBJECT  
96 -  
97 - Q_PROPERTY(QString principalShapePath READ get_principalShapePath WRITE set_principalShapePath RESET reset_principalShapePath STORED false)  
98 - BR_PROPERTY(QString, principalShapePath, QString())  
99 -  
100 - Eigen::MatrixXf meanShape;  
101 -  
102 - void train(const TemplateList &data)  
103 - {  
104 - QList< QList<cv::Point2f> > normalizedPoints;  
105 -  
106 - // Normalize all sets of points  
107 - foreach (br::Template datum, data) {  
108 - QList<cv::Point2f> points = OpenCVUtils::toPoints(datum.file.points());  
109 -  
110 - if (points.empty()) {  
111 - continue;  
112 - }  
113 -  
114 - cv::Scalar mean = cv::mean(points.toVector().toStdVector());  
115 - for (int i = 0; i < points.size(); i++) {  
116 - points[i].x -= mean[0];  
117 - points[i].y -= mean[1];  
118 - }  
119 -  
120 - float norm = cv::norm(points.toVector().toStdVector());  
121 - for (int i = 0; i < points.size(); i++) {  
122 - points[i].x /= norm;  
123 - points[i].y /= norm;  
124 - }  
125 -  
126 - normalizedPoints.append(points);  
127 - }  
128 -  
129 - // Determine mean shape  
130 - Eigen::MatrixXf shapeTest(normalizedPoints[0].size(), 2);  
131 -  
132 - cv::Mat shapeBuffer(normalizedPoints[0].size(), 2, CV_32F);  
133 -  
134 - for (int i = 0; i < normalizedPoints[0].size(); i++) {  
135 -  
136 - double x = 0;  
137 - double y = 0;  
138 -  
139 - for (int j = 0; j < normalizedPoints.size(); j++) {  
140 - x += normalizedPoints[j][i].x;  
141 - y += normalizedPoints[j][i].y;  
142 - }  
143 -  
144 - x /= (double)normalizedPoints.size();  
145 - y /= (double)normalizedPoints.size();  
146 -  
147 - shapeBuffer.at<float>(i,0) = x;  
148 - shapeBuffer.at<float>(i,1) = y;  
149 -  
150 - shapeTest(i,0) = x;  
151 - shapeTest(i,1) = y;  
152 - }  
153 -  
154 - meanShape = shapeTest;  
155 - }  
156 -  
157 - void project(const Template &src, Template &dst) const  
158 - {  
159 - QList<QPointF> points = src.file.points();  
160 -  
161 - cv::Scalar mean = cv::mean(OpenCVUtils::toPoints(points).toVector().toStdVector());  
162 -  
163 - for (int i = 0; i < points.size(); i++) points[i] -= QPointF(mean[0],mean[1]);  
164 -  
165 - float norm = cv::norm(OpenCVUtils::toPoints(points).toVector().toStdVector());  
166 -  
167 - Eigen::MatrixXf srcPoints(points.size(), 2);  
168 - for (int i = 0; i < points.size(); i++) {  
169 - srcPoints(i,0) = points[i].x()/norm;  
170 - srcPoints(i,1) = points[i].y()/norm;  
171 - }  
172 -  
173 - Eigen::JacobiSVD<Eigen::MatrixXf> svd(srcPoints.transpose()*meanShape, Eigen::ComputeThinU | Eigen::ComputeThinV);  
174 -  
175 - Eigen::MatrixXf R = svd.matrixU()*svd.matrixV().transpose();  
176 -  
177 - std::cout << R(1,0) << std::endl;  
178 - // Determine transformation matrix  
179 -  
180 - // Apply transformation matrix  
181 - //dst.file.setPoints(meanShape);*/  
182 - dst.m() = src.m();  
183 - }  
184 -  
185 -};  
186 -  
187 -BR_REGISTER(Transform, ProcrustesTransform)  
188 -  
189 } // namespace br 87 } // namespace br
190 88
191 #include "stasm4.moc" 89 #include "stasm4.moc"