Commit 260843b51f0686b00f13653ce85320c6f39dc985
1 parent
71e41b4a
Improved functionality for texture mapping
Showing
2 changed files
with
47 additions
and
29 deletions
openbr/plugins/landmarks.cpp
| @@ -232,29 +232,15 @@ class ProcrustesAlignTransform : public Transform | @@ -232,29 +232,15 @@ class ProcrustesAlignTransform : public Transform | ||
| 232 | 232 | ||
| 233 | //Normalize rotation | 233 | //Normalize rotation |
| 234 | if (!useFirst) { | 234 | if (!useFirst) { |
| 235 | - MatrixXf refPrev; | ||
| 236 | - referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); | ||
| 237 | - float diff = FLT_MAX; | ||
| 238 | - float diffDelta = FLT_MAX; | ||
| 239 | - while (diff > 1e-5 && diffDelta > 1e-5) {//iterate until reference shape is stable | ||
| 240 | - refPrev = referenceShape; | ||
| 241 | - | ||
| 242 | - for (int j = 0; j < points.cols(); j++) { | ||
| 243 | - MatrixXf p = vectorToMatrix(points.col(j)); | ||
| 244 | - MatrixXf R = getRotation(referenceShape, p); | ||
| 245 | - p = p * R; | ||
| 246 | - points.col(j) = matrixToVector(p); | ||
| 247 | - } | ||
| 248 | - referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); | ||
| 249 | - float temp = diff; | ||
| 250 | - diff = (matrixToVector(referenceShape) - matrixToVector(refPrev)).norm(); | ||
| 251 | - diffDelta = abs(diff - temp); | ||
| 252 | - } | ||
| 253 | - | ||
| 254 | referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); | 235 | referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); |
| 255 | } else { | 236 | } else { |
| 256 | referenceShape = vectorToMatrix(points.col(0)); | 237 | referenceShape = vectorToMatrix(points.col(0)); |
| 257 | - referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); | 238 | + } |
| 239 | + | ||
| 240 | + for (int i = 0; i < points.cols(); i++) { | ||
| 241 | + MatrixXf p = vectorToMatrix(points.col(i)); | ||
| 242 | + MatrixXf R = getRotation(referenceShape, p); | ||
| 243 | + points.col(i) = matrixToVector(p * R); | ||
| 258 | } | 244 | } |
| 259 | 245 | ||
| 260 | //Choose crop boundaries and adjustments that captures most data | 246 | //Choose crop boundaries and adjustments that captures most data |
| @@ -287,10 +273,10 @@ class ProcrustesAlignTransform : public Transform | @@ -287,10 +273,10 @@ class ProcrustesAlignTransform : public Transform | ||
| 287 | maxYs(j) = maxY; | 273 | maxYs(j) = maxY; |
| 288 | } | 274 | } |
| 289 | 275 | ||
| 290 | - minX = eigMean(minXs) - 1 * eigStd(minXs); | ||
| 291 | - minY = eigMean(minYs) - 1 * eigStd(minYs); | ||
| 292 | - maxX = eigMean(maxXs) + 1 * eigStd(maxXs); | ||
| 293 | - maxY = eigMean(maxYs) + 1 * eigStd(maxYs); | 276 | + minX = eigMean(minXs) - 0 * eigStd(minXs); |
| 277 | + minY = eigMean(minYs) - 0 * eigStd(minYs); | ||
| 278 | + maxX = eigMean(maxXs) + 0 * eigStd(maxXs); | ||
| 279 | + maxY = eigMean(maxYs) + 0 * eigStd(maxYs); | ||
| 294 | aspectRatio = (maxX - minX) / (maxY - minY); | 280 | aspectRatio = (maxX - minX) / (maxY - minY); |
| 295 | } | 281 | } |
| 296 | 282 | ||
| @@ -325,6 +311,7 @@ class ProcrustesAlignTransform : public Transform | @@ -325,6 +311,7 @@ class ProcrustesAlignTransform : public Transform | ||
| 325 | dst = src; | 311 | dst = src; |
| 326 | dst.file.setList<QPointF>("ProcrustesPoints", procrustesPoints); | 312 | dst.file.setList<QPointF>("ProcrustesPoints", procrustesPoints); |
| 327 | dst.file.set("ProcrustesBound", QRectF(0, 0, width + 2 * padding, (qRound(width / aspectRatio) + 2 * padding))); | 313 | dst.file.set("ProcrustesBound", QRectF(0, 0, width + 2 * padding, (qRound(width / aspectRatio) + 2 * padding))); |
| 314 | + dst.file.set("ProcrustesPadding", padding); | ||
| 328 | } | 315 | } |
| 329 | 316 | ||
| 330 | void store(QDataStream &stream) const | 317 | void store(QDataStream &stream) const |
| @@ -502,7 +489,7 @@ class TextureMapTransform : public UntrainableTransform | @@ -502,7 +489,7 @@ class TextureMapTransform : public UntrainableTransform | ||
| 502 | { | 489 | { |
| 503 | Q_OBJECT | 490 | Q_OBJECT |
| 504 | 491 | ||
| 505 | - static QRectF getBounds(QList<QPointF> points) { | 492 | + static QRectF getBounds(QList<QPointF> points, int dstPadding) { |
| 506 | float srcMinX = FLT_MAX; | 493 | float srcMinX = FLT_MAX; |
| 507 | float srcMinY = FLT_MAX; | 494 | float srcMinY = FLT_MAX; |
| 508 | float srcMaxX = -FLT_MAX; | 495 | float srcMaxX = -FLT_MAX; |
| @@ -514,8 +501,7 @@ class TextureMapTransform : public UntrainableTransform | @@ -514,8 +501,7 @@ class TextureMapTransform : public UntrainableTransform | ||
| 514 | if (points[i].y() > srcMaxY) srcMaxY = points[i].y(); | 501 | if (points[i].y() > srcMaxY) srcMaxY = points[i].y(); |
| 515 | } | 502 | } |
| 516 | 503 | ||
| 517 | - float padding = (srcMaxX - srcMinX) / 80 * 16; | ||
| 518 | - //padding = 8; | 504 | + float padding = (srcMaxX - srcMinX) / 80 * dstPadding; |
| 519 | return QRectF(qRound(srcMinX - padding), qRound(srcMinY - padding), qRound(srcMaxX - srcMinX + 2 * padding), qRound(srcMaxY - srcMinY + 2 * padding)); | 505 | return QRectF(qRound(srcMinX - padding), qRound(srcMinY - padding), qRound(srcMaxX - srcMinX + 2 * padding), qRound(srcMaxY - srcMinY + 2 * padding)); |
| 520 | } | 506 | } |
| 521 | 507 | ||
| @@ -574,8 +560,8 @@ class TextureMapTransform : public UntrainableTransform | @@ -574,8 +560,8 @@ class TextureMapTransform : public UntrainableTransform | ||
| 574 | { | 560 | { |
| 575 | QList<QPointF> dstPoints = dst.file.getList<QPointF>("ProcrustesPoints"); | 561 | QList<QPointF> dstPoints = dst.file.getList<QPointF>("ProcrustesPoints"); |
| 576 | QList<QPointF> srcPoints = dst.file.points(); | 562 | QList<QPointF> srcPoints = dst.file.points(); |
| 577 | - QRectF dstBound = dst.file.get<QRectF>("ProcrustesBound");// getBounds(dstPoints, 8); | ||
| 578 | - QRectF srcBound = getBounds(srcPoints); | 563 | + QRectF dstBound = dst.file.get<QRectF>("ProcrustesBound"); |
| 564 | + QRectF srcBound = getBounds(srcPoints, dst.file.get<int>("ProcrustesPadding")); | ||
| 579 | if (dstPoints.empty() || srcPoints.empty()) { | 565 | if (dstPoints.empty() || srcPoints.empty()) { |
| 580 | dst = src; | 566 | dst = src; |
| 581 | if (Globals->verbose) qWarning("Delauney triangulation failed because points or rects are empty."); | 567 | if (Globals->verbose) qWarning("Delauney triangulation failed because points or rects are empty."); |
| @@ -635,6 +621,36 @@ class TextureMapTransform : public UntrainableTransform | @@ -635,6 +621,36 @@ class TextureMapTransform : public UntrainableTransform | ||
| 635 | BR_REGISTER(Transform, TextureMapTransform) | 621 | BR_REGISTER(Transform, TextureMapTransform) |
| 636 | 622 | ||
| 637 | /*! | 623 | /*! |
| 624 | + * \ingroup initializers | ||
| 625 | + * \brief Initialize Procrustes croppings | ||
| 626 | + * \author Brendan Klare \cite bklare | ||
| 627 | + */ | ||
| 628 | +class ProcrustesInitializer : public Initializer | ||
| 629 | +{ | ||
| 630 | + Q_OBJECT | ||
| 631 | + | ||
| 632 | + void initialize() const | ||
| 633 | + { | ||
| 634 | + Globals->abbreviations.insert("ProcrustesStasmFace","ProcrustesAlign(padding=16)+TextureMap+Resize(48,48)"); | ||
| 635 | + Globals->abbreviations.insert("ProcrustesStasmEyes","SelectPoints([28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47])+ProcrustesAlign(padding=8)+TextureMap+Resize(24,48)"); | ||
| 636 | + Globals->abbreviations.insert("ProcrustesStasmPeriocular","SelectPoints([28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,16,17,18,19,20,21,22,23,24,25,26,27])+ProcrustesAlign(padding=8)+TextureMap+Resize(36,48)"); | ||
| 637 | + Globals->abbreviations.insert("ProcrustesStasmBrow","SelectPoints([16,17,18,19,20,21,22,23,24,25,26,27])+ProcrustesAlign(padding=8)+TextureMap+Resize(24,48)"); | ||
| 638 | + Globals->abbreviations.insert("ProcrustesStasmNose","SelectPoints([48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58])+ProcrustesAlign(padding=8)+TextureMap+Resize(36,48)"); | ||
| 639 | + Globals->abbreviations.insert("ProcrustesStasmMouth","SelectPoints([59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76])+ProcrustesAlign(padding=10)+TextureMap+Resize(36,48)"); | ||
| 640 | + Globals->abbreviations.insert("ProcrustesStasmJaw", "SelectPoints([2,3,4,5,6,7,8,9,10])+ProcrustesAlign(padding=8)+TextureMap+Resize(36,48)"); | ||
| 641 | + | ||
| 642 | + Globals->abbreviations.insert("ProcrustesLargeStasmFace","ProcrustesAlign(padding=16)+TextureMap+Resize(480,480)"); | ||
| 643 | + Globals->abbreviations.insert("ProcrustesLargeStasmEyes","SelectPoints([28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47])+ProcrustesAlign(padding=8)+TextureMap+Resize(240,480)"); | ||
| 644 | + Globals->abbreviations.insert("ProcrustesLargeStasmPeriocular","SelectPoints([28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,16,17,18,19,20,21,22,23,24,25,26,27])+ProcrustesAlign(padding=8)+TextureMap+Resize(360,480)"); | ||
| 645 | + Globals->abbreviations.insert("ProcrustesLargeStasmBrow","SelectPoints([16,17,18,19,20,21,22,23,24,25,26,27])+ProcrustesAlign(padding=8)+TextureMap+Resize(240,480)"); | ||
| 646 | + Globals->abbreviations.insert("ProcrustesLargeStasmNose","SelectPoints([48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58])+ProcrustesAlign(padding=8)+TextureMap+Resize(360,480)"); | ||
| 647 | + Globals->abbreviations.insert("ProcrustesLargeStasmMouth","SelectPoints([59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76])+ProcrustesAlign(padding=20)+TextureMap+Resize(360,480)"); | ||
| 648 | + Globals->abbreviations.insert("ProcrustesLargeStasmJaw", "SelectPoints([2,3,4,5,6,7,8,9,10])+ProcrustesAlign(padding=8)+TextureMap+Resize(360,480)"); | ||
| 649 | + } | ||
| 650 | +}; | ||
| 651 | +BR_REGISTER(Initializer, ProcrustesInitializer) | ||
| 652 | + | ||
| 653 | +/*! | ||
| 638 | * \ingroup transforms | 654 | * \ingroup transforms |
| 639 | * \brief Creates a Delaunay triangulation based on a set of points | 655 | * \brief Creates a Delaunay triangulation based on a set of points |
| 640 | * \author Scott Klum \cite sklum | 656 | * \author Scott Klum \cite sklum |
openbr/plugins/stasm4.cpp
| @@ -37,6 +37,8 @@ class StasmInitializer : public Initializer | @@ -37,6 +37,8 @@ class StasmInitializer : public Initializer | ||
| 37 | { | 37 | { |
| 38 | Globals->abbreviations.insert("RectFromStasmEyes","RectFromPoints([28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47],0.3,5.3)"); | 38 | Globals->abbreviations.insert("RectFromStasmEyes","RectFromPoints([28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47],0.3,5.3)"); |
| 39 | Globals->abbreviations.insert("RectFromStasmBrow","RectFromPoints([16,17,18,19,20,21,22,23,24,25,26,27],0.15,5)"); | 39 | Globals->abbreviations.insert("RectFromStasmBrow","RectFromPoints([16,17,18,19,20,21,22,23,24,25,26,27],0.15,5)"); |
| 40 | + Globals->abbreviations.insert("RectFromStasmPeriocular","RectFromPoints([28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,16,17,18,19,20,21,22,23,24,25,26,27]],0.3,5.3)"); | ||
| 41 | + Globals->abbreviations.insert("RectFromStasmBrow","RectFromPoints([16,17,18,19,20,21,22,23,24,25,26,27],0.15,5)"); | ||
| 40 | Globals->abbreviations.insert("RectFromStasmNose","RectFromPoints([48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58],0.15,1.15)"); | 42 | Globals->abbreviations.insert("RectFromStasmNose","RectFromPoints([48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58],0.15,1.15)"); |
| 41 | Globals->abbreviations.insert("RectFromStasmNoseWithBridge", "RectFromPoints([21, 22, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58],0.15,.6)"); | 43 | Globals->abbreviations.insert("RectFromStasmNoseWithBridge", "RectFromPoints([21, 22, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58],0.15,.6)"); |
| 42 | Globals->abbreviations.insert("RectFromStasmMouth","RectFromPoints([59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76],0.3,2)"); | 44 | Globals->abbreviations.insert("RectFromStasmMouth","RectFromPoints([59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76],0.3,2)"); |