Commit 4261d8e6a1050c7c68bf50719350524c354511c4

Authored by Brendan Klare
1 parent 9f84bcdb

Finalized procrustes training and alignment

Showing 1 changed file with 66 additions and 15 deletions
openbr/plugins/landmarks.cpp
... ... @@ -146,9 +146,24 @@ class ProcrustesAlignTransform : public Transform
146 146 Q_OBJECT
147 147  
148 148 Q_PROPERTY(float width READ get_width WRITE set_width RESET reset_width STORED false)
149   - BR_PROPERTY(float, width, true)
  149 + Q_PROPERTY(float padding READ get_padding WRITE set_padding RESET reset_padding STORED false)
  150 + BR_PROPERTY(float, width, 80)
  151 + BR_PROPERTY(float, padding, 8)
150 152  
151 153 Eigen::MatrixXf referenceShape;
  154 + float minX;
  155 + float minY;
  156 + float maxX;
  157 + float maxY;
  158 + float aspectRatio;
  159 +
  160 + void init() {
  161 + minX = FLT_MAX,
  162 + minY = FLT_MAX,
  163 + maxX = -FLT_MAX,
  164 + maxY = -FLT_MAX;
  165 + aspectRatio = 0;
  166 + }
152 167  
153 168 MatrixXf getRotation(MatrixXf ref, MatrixXf sample) const {
154 169 MatrixXf R = ref.transpose() * sample;
... ... @@ -180,7 +195,6 @@ class ProcrustesAlignTransform : public Transform
180 195 return vector;
181 196 }
182 197  
183   -
184 198 void train(const TemplateList &data)
185 199 {
186 200 MatrixXf points(data[0].file.points().size() * 2, data.size());
... ... @@ -206,7 +220,6 @@ class ProcrustesAlignTransform : public Transform
206 220 }
207 221 }
208 222  
209   -
210 223 //normalize scale
211 224 for (int i = 0; i < points.cols(); i++)
212 225 points.col(i) = points.col(i) / points.col(i).norm();
... ... @@ -214,17 +227,40 @@ class ProcrustesAlignTransform : public Transform
214 227 //Normalize rotation
215 228 MatrixXf refPrev;
216 229 referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols());
217   -
218   - for (int j = 0; j < points.cols(); j++) {
219   - MatrixXf p = vectorToMatrix(points.col(j));
220   - MatrixXf R = getRotation(referenceShape, p);
221   - p = p * R;
222   - points.col(j) = matrixToVector(p);
  230 + float diff = FLT_MAX;
  231 + while (diff > 1e-5) {//iterate until reference shape is stable
  232 + refPrev = referenceShape;
  233 +
  234 + for (int j = 0; j < points.cols(); j++) {
  235 + MatrixXf p = vectorToMatrix(points.col(j));
  236 + MatrixXf R = getRotation(referenceShape, p);
  237 + p = p * R.transpose();
  238 + points.col(j) = matrixToVector(p);
  239 + }
  240 + referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols());
  241 + diff = (matrixToVector(referenceShape) - matrixToVector(refPrev)).norm();
223 242 }
224 243  
225 244 referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols());
226   - }
227 245  
  246 + //Choose crop boundaries and adjustments that captures all data
  247 + for (int i = 0; i < points.rows(); i++) {
  248 + for (int j = 0; j < points.cols(); j++) {
  249 + if (i % 2 == 0) {
  250 + if (points(i,j) > maxX)
  251 + maxX = points(i, j);
  252 + if (points(i,j) < minX)
  253 + minX = points(i, j);
  254 + } else {
  255 + if (points(i,j) > maxY)
  256 + maxY = points(i, j);
  257 + if (points(i,j) < minY)
  258 + minY = points(i, j);
  259 + }
  260 + }
  261 + }
  262 + aspectRatio = (maxX - minX) / (maxY - minY);
  263 + }
228 264  
229 265 void project(const Template &src, Template &dst) const
230 266 {
... ... @@ -234,7 +270,6 @@ class ProcrustesAlignTransform : public Transform
234 270 p(i * 2) = imagePoints[i].x();
235 271 p(i * 2 + 1) = imagePoints[i].y();
236 272 }
237   - float norm = p.norm();
238 273 p = vectorToMatrix(p);
239 274  
240 275 //Nomralize translation
... ... @@ -242,30 +277,46 @@ class ProcrustesAlignTransform : public Transform
242 277 p.col(1) = p.col(1) - MatrixXf::Ones(p.rows(),1) * (p.col(1).sum() / p.rows());
243 278  
244 279 //Normalize scale
245   - p /= norm;
  280 + p /= matrixToVector(p).norm();
246 281  
247 282 //Normalize rotation
248 283 MatrixXf R = getRotation(referenceShape, p);
249   - p = p * R;
  284 + p = p * R.transpose();
250 285  
  286 + for (int i = 0; i < p.rows(); i++) {
  287 + }
  288 +
  289 + //Translate and scale into output space and store in output list
251 290 QList<QPointF> procrustesPoints;
252 291 for (int i = 0; i < p.rows(); i++)
253   - procrustesPoints.append(QPointF(p(i, 0), p(i, 1)));
  292 + procrustesPoints.append( QPointF(
  293 + (p(i, 0) - minX) / (maxX - minX) * (width - 1) + padding,
  294 + (p(i, 1) - minY) / (maxY - minY) * (qRound( width / aspectRatio) - 1) + padding));
254 295  
255 296 dst = src;
256 297 dst.file.setList<QPointF>("ProcrustesPoints", procrustesPoints);
  298 + dst.file.set("ProcrustesBound", QRectF(0, 0, width + 2 * padding, (qRound(width / aspectRatio) + 2 * padding)));
257 299 }
258 300  
259 301 void store(QDataStream &stream) const
260 302 {
261 303 stream << referenceShape;
  304 + stream << minX;
  305 + stream << minY;
  306 + stream << maxX;
  307 + stream << maxY;
  308 + stream << aspectRatio;
262 309 }
263 310  
264 311 void load(QDataStream &stream)
265 312 {
266 313 stream >> referenceShape;
  314 + stream >> minX;
  315 + stream >> minY;
  316 + stream >> maxX;
  317 + stream >> maxY;
  318 + stream >> aspectRatio;
267 319 }
268   -
269 320 };
270 321  
271 322 BR_REGISTER(Transform, ProcrustesAlignTransform)
... ...