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 201 Q_PROPERTY(QList<int> indices READ get_indices WRITE set_indices RESET reset_indices STORED false)
202 202 Q_PROPERTY(double padding READ get_padding WRITE set_padding RESET reset_padding STORED false)
203 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 205 BR_PROPERTY(QList<int>, indices, QList<int>())
206 206 BR_PROPERTY(double, padding, 0)
207 207 BR_PROPERTY(double, aspectRatio, 1.0)
... ... @@ -220,13 +220,15 @@ class RectFromPointsTransform : public UntrainableTransform
220 220 int maxX, maxY;
221 221 maxX = maxY = -std::numeric_limits<int>::max();
222 222  
  223 + QList<QPointF> points;
  224 +
223 225 foreach(int index, indices) {
224 226 if (src.file.points().size() > index) {
225 227 if (src.file.points()[index].x() < minX) minX = src.file.points()[index].x();
226 228 if (src.file.points()[index].x() > maxX) maxX = src.file.points()[index].x();
227 229 if (src.file.points()[index].y() < minY) minY = src.file.points()[index].y();
228 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 240 double deltaHeight = width/aspectRatio - height;
239 241 height += deltaHeight;
240 242  
  243 + dst.file.setPoints(points);
  244 +
241 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 246 else dst.m() = src.m();
243 247 }
... ...
openbr/plugins/stasm4.cpp
... ... @@ -7,6 +7,7 @@
7 7 #include <QString>
8 8 #include <Eigen/SVD>
9 9  
  10 +using namespace std;
10 11 using namespace cv;
11 12  
12 13 namespace br
... ... @@ -83,109 +84,6 @@ class StasmTransform : public UntrainableTransform
83 84  
84 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 87 } // namespace br
190 88  
191 89 #include "stasm4.moc"
... ...