Commit 9bf09e4ddc83dd4c6b023b28d0374f2e38dfa042
1 parent
59acf294
In the middle of debugging, saving progress...
Showing
1 changed file
with
52 additions
and
30 deletions
openbr/plugins/landmarks.cpp
| @@ -268,19 +268,11 @@ class ProcrustesAlignTransform : public Transform | @@ -268,19 +268,11 @@ class ProcrustesAlignTransform : public Transform | ||
| 268 | 268 | ||
| 269 | void project(const Template &src, Template &dst) const | 269 | void project(const Template &src, Template &dst) const |
| 270 | { | 270 | { |
| 271 | - float srcMinX = FLT_MAX; | ||
| 272 | - float srcMinY = FLT_MAX; | ||
| 273 | - float srcMaxX = -FLT_MAX; | ||
| 274 | - float srcMaxY = -FLT_MAX; | ||
| 275 | QList<QPointF> imagePoints = src.file.points(); | 271 | QList<QPointF> imagePoints = src.file.points(); |
| 276 | MatrixXf p(imagePoints.size() * 2, 1); | 272 | MatrixXf p(imagePoints.size() * 2, 1); |
| 277 | for (int i = 0; i < imagePoints.size(); i++) { | 273 | for (int i = 0; i < imagePoints.size(); i++) { |
| 278 | p(i * 2) = imagePoints[i].x(); | 274 | p(i * 2) = imagePoints[i].x(); |
| 279 | p(i * 2 + 1) = imagePoints[i].y(); | 275 | p(i * 2 + 1) = imagePoints[i].y(); |
| 280 | - if (imagePoints[i].x() < srcMinX) srcMinX = imagePoints[i].x(); | ||
| 281 | - if (imagePoints[i].y() < srcMinY) srcMinY = imagePoints[i].y(); | ||
| 282 | - if (imagePoints[i].x() < srcMaxX) srcMaxX = imagePoints[i].x(); | ||
| 283 | - if (imagePoints[i].y() < srcMaxY) srcMaxY = imagePoints[i].y(); | ||
| 284 | } | 276 | } |
| 285 | p = vectorToMatrix(p); | 277 | p = vectorToMatrix(p); |
| 286 | 278 | ||
| @@ -305,9 +297,6 @@ class ProcrustesAlignTransform : public Transform | @@ -305,9 +297,6 @@ class ProcrustesAlignTransform : public Transform | ||
| 305 | dst = src; | 297 | dst = src; |
| 306 | dst.file.setList<QPointF>("ProcrustesPoints", procrustesPoints); | 298 | dst.file.setList<QPointF>("ProcrustesPoints", procrustesPoints); |
| 307 | dst.file.set("ProcrustesBound", QRectF(0, 0, width + 2 * padding, (qRound(width / aspectRatio) + 2 * padding))); | 299 | dst.file.set("ProcrustesBound", QRectF(0, 0, width + 2 * padding, (qRound(width / aspectRatio) + 2 * padding))); |
| 308 | - dst.file.set("ProcrustesSrcBound", QRectF(qRound(srcMinX - padding), qRound(srcMinY - padding), | ||
| 309 | - qRound(srcMaxX - srcMinX + 2 * padding), | ||
| 310 | - qRound(srcMaxY - srcMinY + 2 * padding))); | ||
| 311 | } | 300 | } |
| 312 | 301 | ||
| 313 | void store(QDataStream &stream) const | 302 | void store(QDataStream &stream) const |
| @@ -347,7 +336,7 @@ class DelaunayTransform : public UntrainableTransform | @@ -347,7 +336,7 @@ class DelaunayTransform : public UntrainableTransform | ||
| 347 | BR_PROPERTY(float, scaleFactor, 1) | 336 | BR_PROPERTY(float, scaleFactor, 1) |
| 348 | BR_PROPERTY(bool, warp, true) | 337 | BR_PROPERTY(bool, warp, true) |
| 349 | 338 | ||
| 350 | - void project(const Template &src, Template &dst, ) const | 339 | + void project(const Template &src, Template &dst) const |
| 351 | { | 340 | { |
| 352 | QList<QPointF> points = src.file.points(); | 341 | QList<QPointF> points = src.file.points(); |
| 353 | QList<QRectF> rects = src.file.rects(); | 342 | QList<QRectF> rects = src.file.rects(); |
| @@ -490,13 +479,32 @@ class TextureMapTransform : public UntrainableTransform | @@ -490,13 +479,32 @@ class TextureMapTransform : public UntrainableTransform | ||
| 490 | BR_PROPERTY(float, scaleFactor, 1) | 479 | BR_PROPERTY(float, scaleFactor, 1) |
| 491 | BR_PROPERTY(bool, warp, true) | 480 | BR_PROPERTY(bool, warp, true) |
| 492 | 481 | ||
| 493 | - QList<QPointF> getTriangulation(QList<QPointF> points, QRect bound) { | 482 | + static QRectF getBounds(QList<QPointF> points, int padding) { |
| 483 | + float srcMinX = FLT_MAX; | ||
| 484 | + float srcMinY = FLT_MAX; | ||
| 485 | + float srcMaxX = -FLT_MAX; | ||
| 486 | + float srcMaxY = -FLT_MAX; | ||
| 487 | + for (int i = 0; i < points.size(); i++) { | ||
| 488 | + if (points[i].x() < srcMinX) srcMinX = points[i].x(); | ||
| 489 | + if (points[i].y() < srcMinY) srcMinY = points[i].y(); | ||
| 490 | + if (points[i].x() > srcMaxX) srcMaxX = points[i].x(); | ||
| 491 | + if (points[i].y() > srcMaxY) srcMaxY = points[i].y(); | ||
| 492 | + } | ||
| 493 | + return QRectF(qRound(srcMinX - padding), qRound(srcMinY - padding), qRound(srcMaxX - srcMinX + 2 * padding), qRound(srcMaxY - srcMinY + 2 * padding)); | ||
| 494 | + } | ||
| 495 | + QList<QPointF> getTriangulation(const QList<QPointF> _points, const QRectF bound) const { | ||
| 496 | + QList<QPointF> points(_points); | ||
| 497 | + /* | ||
| 494 | points.append(bound.topLeft()); | 498 | points.append(bound.topLeft()); |
| 495 | - points.append(bound.topRight()); | ||
| 496 | - points.append(bound.bottomLeft()); | ||
| 497 | - points.append(bound.bottomRight()); | ||
| 498 | - | ||
| 499 | - Subdiv2D subdiv(); | 499 | + points.append(QPointF(bound.right() - 1, bound.top())); |
| 500 | + points.append(QPointF(bound.left(), bound.bottom() - 1)); | ||
| 501 | + points.append(QPointF(bound.right() - 1, bound.bottom() - 1)); | ||
| 502 | + points.append(QPointF(bound.left() + bound.width() / 2, bound.top())); | ||
| 503 | + points.append(QPointF(bound.left() + bound.width() / 2, bound.bottom() - 1)); | ||
| 504 | + points.append(QPointF(bound.left(), bound.top() + bound.height() / 2)); | ||
| 505 | + points.append(QPointF(bound.right() - 1, bound.top() + bound.height() / 2)); | ||
| 506 | + */ | ||
| 507 | + Subdiv2D subdiv(OpenCVUtils::toRect(bound)); | ||
| 500 | for (int i = 0; i < points.size(); i++) | 508 | for (int i = 0; i < points.size(); i++) |
| 501 | subdiv.insert(OpenCVUtils::toPoint(points[i])); | 509 | subdiv.insert(OpenCVUtils::toPoint(points[i])); |
| 502 | 510 | ||
| @@ -504,6 +512,8 @@ class TextureMapTransform : public UntrainableTransform | @@ -504,6 +512,8 @@ class TextureMapTransform : public UntrainableTransform | ||
| 504 | subdiv.getTriangleList(triangleList); | 512 | subdiv.getTriangleList(triangleList); |
| 505 | 513 | ||
| 506 | QList<QPointF> validTriangles; | 514 | QList<QPointF> validTriangles; |
| 515 | +static int SCNT = 0; | ||
| 516 | +MatrixXf P(triangleList.size() * 3,2); | ||
| 507 | for (size_t i = 0; i < triangleList.size(); i++) { | 517 | for (size_t i = 0; i < triangleList.size(); i++) { |
| 508 | bool valid = true; | 518 | bool valid = true; |
| 509 | QList<QPointF> vertices; | 519 | QList<QPointF> vertices; |
| @@ -511,23 +521,31 @@ class TextureMapTransform : public UntrainableTransform | @@ -511,23 +521,31 @@ class TextureMapTransform : public UntrainableTransform | ||
| 511 | vertices.append(QPointF(triangleList[i][2],triangleList[i][3])); | 521 | vertices.append(QPointF(triangleList[i][2],triangleList[i][3])); |
| 512 | vertices.append(QPointF(triangleList[i][4],triangleList[i][5])); | 522 | vertices.append(QPointF(triangleList[i][4],triangleList[i][5])); |
| 513 | for (int j = 0; j < 3; j++) | 523 | for (int j = 0; j < 3; j++) |
| 514 | - if (vertices[j].x() > cols || vertices[j].y() > rows || vertices[j].x() < 0 || vertices[j].y() < 0) | 524 | + if (vertices[j].x() > bound.right() || vertices[j].y() > bound.bottom() || vertices[j].x() < bound.left() || vertices[j].y() < bound.top()) |
| 515 | valid = false; | 525 | valid = false; |
| 516 | - | 526 | +for (int j = 0; j < 3;j++) { |
| 527 | +P(i*3+j,0) = vertices[j].x(); | ||
| 528 | +P(i*3+j,1) = vertices[j].y(); | ||
| 529 | +} | ||
| 517 | if (valid) | 530 | if (valid) |
| 518 | validTriangles.append(vertices); | 531 | validTriangles.append(vertices); |
| 519 | } | 532 | } |
| 533 | +//writeEigen(P, QString("Temp/p%1.bin").arg(SCNT++)); | ||
| 520 | 534 | ||
| 535 | +MatrixXf P(validTriangles.size(),2); | ||
| 536 | +for (int j = 0; j < validTriangles.size() ;j++) { | ||
| 537 | +P(i*3+j,0) = vertices[j].x(); | ||
| 538 | +P(i*3+j,1) = vertices[j].y(); | ||
| 539 | +} | ||
| 521 | return validTriangles; | 540 | return validTriangles; |
| 522 | } | 541 | } |
| 523 | 542 | ||
| 524 | void project(const Template &src, Template &dst) const | 543 | void project(const Template &src, Template &dst) const |
| 525 | { | 544 | { |
| 526 | - QList<QPointF> dstPoints = dst.file.setList<QPointF>("ProcrustesPoints", procrustesPoints); | ||
| 527 | - QRectF dstBound = dst.file.setList<QPointF>("ProcrustesBound", procrustesPoints); | 545 | + QList<QPointF> dstPoints = dst.file.getList<QPointF>("ProcrustesPoints"); |
| 528 | QList<QPointF> srcPoints = dst.file.points(); | 546 | QList<QPointF> srcPoints = dst.file.points(); |
| 529 | - QRectF srcBound = dst.file.setList<QPointF>("ProcrustesSrcBound", procrustesPoints); | ||
| 530 | - | 547 | + QRectF dstBound = getBounds(dstPoints, 8); |
| 548 | + QRectF srcBound = getBounds(srcPoints, 8); | ||
| 531 | if (dstPoints.empty() || srcPoints.empty()) { | 549 | if (dstPoints.empty() || srcPoints.empty()) { |
| 532 | dst = src; | 550 | dst = src; |
| 533 | if (Globals->verbose) qWarning("Delauney triangulation failed because points or rects are empty."); | 551 | if (Globals->verbose) qWarning("Delauney triangulation failed because points or rects are empty."); |
| @@ -538,18 +556,19 @@ class TextureMapTransform : public UntrainableTransform | @@ -538,18 +556,19 @@ class TextureMapTransform : public UntrainableTransform | ||
| 538 | QList<QPointF> srcTri = getTriangulation(srcPoints, srcBound); | 556 | QList<QPointF> srcTri = getTriangulation(srcPoints, srcBound); |
| 539 | 557 | ||
| 540 | dst.m() = Mat::zeros(dstBound.height(), dstBound.width(), src.m().type()); | 558 | dst.m() = Mat::zeros(dstBound.height(), dstBound.width(), src.m().type()); |
| 541 | - for (int i = 0; i < srcTriangles.size(); i+=3) { | 559 | + for (int i = 0; i < srcTri.size(); i+=3) { |
| 542 | Point2f srcPoints[3]; | 560 | Point2f srcPoints[3]; |
| 543 | Point2f dstPoints[3]; | 561 | Point2f dstPoints[3]; |
| 544 | for (int j = 0; j < 3; j++) { | 562 | for (int j = 0; j < 3; j++) { |
| 545 | srcPoints[j] = OpenCVUtils::toPoint(srcTri[i+j]); | 563 | srcPoints[j] = OpenCVUtils::toPoint(srcTri[i+j]); |
| 546 | - srcPoints[j] = OpenCVUtils::toPoint(dstTri[i+j]); | 564 | + dstPoints[j] = OpenCVUtils::toPoint(dstTri[i+j]); |
| 547 | } | 565 | } |
| 548 | 566 | ||
| 549 | Mat buffer(dstBound.height(), dstBound.width(), src.m().type()); | 567 | Mat buffer(dstBound.height(), dstBound.width(), src.m().type()); |
| 550 | - warpAffine(src.m(), buffer, getAffineTransform(srcPoints, dstPoints), Size(cols,rows)); | 568 | + warpAffine(src.m(), buffer, getAffineTransform(srcPoints, dstPoints), Size(dstBound.width(), dstBound.height())); |
| 551 | 569 | ||
| 552 | - Mat mask = Mat::zeros(rows, cols, CV_8UC1); | 570 | + //Mat mask = Mat::zeros(dstBound.height(), dstBound.width(), CV_8UC1); |
| 571 | + Mat mask = Mat::zeros(dstBound.height(), dstBound.width(), src.m().type()); | ||
| 553 | Point maskPoints[1][3]; | 572 | Point maskPoints[1][3]; |
| 554 | maskPoints[0][0] = dstPoints[0]; | 573 | maskPoints[0][0] = dstPoints[0]; |
| 555 | maskPoints[0][1] = dstPoints[1]; | 574 | maskPoints[0][1] = dstPoints[1]; |
| @@ -559,19 +578,22 @@ class TextureMapTransform : public UntrainableTransform | @@ -559,19 +578,22 @@ class TextureMapTransform : public UntrainableTransform | ||
| 559 | 578 | ||
| 560 | Mat output(dstBound.height(), dstBound.width(), src.m().type()); | 579 | Mat output(dstBound.height(), dstBound.width(), src.m().type()); |
| 561 | 580 | ||
| 581 | + /* | ||
| 562 | if (i > 0) { | 582 | if (i > 0) { |
| 563 | Mat overlap; | 583 | Mat overlap; |
| 564 | - bitwise_and(dst.m(),mask,overlap); | 584 | + bitwise_and(dst.m(), mask, overlap); |
| 565 | mask.setTo(0, overlap!=0); | 585 | mask.setTo(0, overlap!=0); |
| 566 | } | 586 | } |
| 587 | + */ | ||
| 567 | 588 | ||
| 568 | bitwise_and(buffer,mask,output); | 589 | bitwise_and(buffer,mask,output); |
| 569 | - | ||
| 570 | dst.m() += output; | 590 | dst.m() += output; |
| 571 | } | 591 | } |
| 572 | } | 592 | } |
| 573 | }; | 593 | }; |
| 574 | 594 | ||
| 595 | +BR_REGISTER(Transform, TextureMapTransform) | ||
| 596 | + | ||
| 575 | /*! | 597 | /*! |
| 576 | * \ingroup transforms | 598 | * \ingroup transforms |
| 577 | * \brief Creates a Delaunay triangulation based on a set of points | 599 | * \brief Creates a Delaunay triangulation based on a set of points |