From 48d184af11d199e4c9079d49d3c910abfcdababc Mon Sep 17 00:00:00 2001 From: Brendan Klare Date: Wed, 16 Jul 2014 23:57:36 -0400 Subject: [PATCH] Killed --- openbr/plugins/landmarks.cpp | 369 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 file changed, 0 insertions(+), 369 deletions(-) diff --git a/openbr/plugins/landmarks.cpp b/openbr/plugins/landmarks.cpp index e8ed289..a64dba8 100644 --- a/openbr/plugins/landmarks.cpp +++ b/openbr/plugins/landmarks.cpp @@ -141,204 +141,6 @@ BR_REGISTER(Transform, ProcrustesTransform) /*! * \ingroup transforms - * \brief Improved procrustes alignment of points, to include a post processing scaling of points - * to faciliate subsequent texture mapping. - * \author Brendan Klare \cite bklare - * \param width Width of output coordinate space (before padding) - * \param padding Amount of padding around the coordinate space - * \param useFirst whether or not to use the first instance as the reference object - */ -class ProcrustesAlignTransform : public Transform -{ - Q_OBJECT - - Q_PROPERTY(float width READ get_width WRITE set_width RESET reset_width STORED false) - Q_PROPERTY(float padding READ get_padding WRITE set_padding RESET reset_padding STORED false) - Q_PROPERTY(bool useFirst READ get_useFirst WRITE set_useFirst RESET reset_useFirst STORED false) - BR_PROPERTY(float, width, 80) - BR_PROPERTY(float, padding, 8) - BR_PROPERTY(bool, useFirst, false) - - - Eigen::MatrixXf referenceShape; - float minX; - float minY; - float maxX; - float maxY; - float aspectRatio; - - void init() { - aspectRatio = 0; - } - - static MatrixXf getRotation(MatrixXf ref, MatrixXf sample) { - MatrixXf R = sample.transpose() * ref; - JacobiSVD svd(R, ComputeFullU | ComputeFullV); - R = svd.matrixU() * svd.matrixV().transpose(); - return R; - } - - //Converts x y points in a single vector to two column matrix - static MatrixXf vectorToMatrix(MatrixXf vector) { - int n = vector.rows(); - MatrixXf matrix(n / 2, 2); - for (int i = 0; i < n / 2; i++) { - for (int j = 0; j < 2; j++) { - matrix(i, j) = vector(i * 2 + j); - } - } - return matrix; - } - - static MatrixXf matrixToVector(MatrixXf matrix) { - int n2 = matrix.rows(); - MatrixXf vector(n2 * 2, 1); - for (int i = 0; i < n2; i++) { - for (int j = 0; j < 2; j++) { - vector(i * 2 + j) = matrix(i, j); - } - } - return vector; - } - - void train(const TemplateList &data) - { - MatrixXf points(data[0].file.points().size() * 2, data.size()); - - // Normalize all sets of points - for (int j = 0; j < data.size(); j++) { - QList imagePoints = data[j].file.points(); - - float meanX = 0, - meanY = 0; - for (int i = 0; i < imagePoints.size(); i++) { - points(i * 2, j) = imagePoints[i].x(); - points(i * 2 + 1, j) = imagePoints[i].y(); - meanX += imagePoints[i].x(); - meanY += imagePoints[i].y(); - } - meanX /= imagePoints.size(); - meanY /= imagePoints.size(); - - for (int i = 0; i < imagePoints.size(); i++) { - points(i * 2, j) -= meanX; - points(i * 2 + 1, j) -= meanY; - } - } - - //normalize scale - for (int i = 0; i < points.cols(); i++) - points.col(i) = points.col(i) / points.col(i).norm(); - - //Normalize rotation - if (!useFirst) { - referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); - } else { - referenceShape = vectorToMatrix(points.col(0)); - } - - for (int i = 0; i < points.cols(); i++) { - MatrixXf p = vectorToMatrix(points.col(i)); - MatrixXf R = getRotation(referenceShape, p); - points.col(i) = matrixToVector(p * R); - } - - //Choose crop boundaries and adjustments that captures most data - MatrixXf minXs(points.cols(),1); - MatrixXf minYs(points.cols(),1); - MatrixXf maxXs(points.cols(),1); - MatrixXf maxYs(points.cols(),1); - for (int j = 0; j < points.cols(); j++) { - minX = FLT_MAX, - minY = FLT_MAX, - maxX = -FLT_MAX, - maxY = -FLT_MAX; - for (int i = 0; i < points.rows(); i++) { - if (i % 2 == 0) { - if (points(i,j) > maxX) - maxX = points(i, j); - if (points(i,j) < minX) - minX = points(i, j); - } else { - if (points(i,j) > maxY) - maxY = points(i, j); - if (points(i,j) < minY) - minY = points(i, j); - } - } - - minXs(j) = minX; - maxXs(j) = maxX; - minYs(j) = minY; - maxYs(j) = maxY; - } - - minX = eigMean(minXs) - 0 * eigStd(minXs); - minY = eigMean(minYs) - 0 * eigStd(minYs); - maxX = eigMean(maxXs) + 0 * eigStd(maxXs); - maxY = eigMean(maxYs) + 0 * eigStd(maxYs); - aspectRatio = (maxX - minX) / (maxY - minY); - } - - void project(const Template &src, Template &dst) const - { - QList imagePoints = src.file.points(); - MatrixXf p(imagePoints.size() * 2, 1); - for (int i = 0; i < imagePoints.size(); i++) { - p(i * 2) = imagePoints[i].x(); - p(i * 2 + 1) = imagePoints[i].y(); - } - p = vectorToMatrix(p); - - //Normalize translation - p.col(0) = p.col(0) - MatrixXf::Ones(p.rows(),1) * (p.col(0).sum() / p.rows()); - p.col(1) = p.col(1) - MatrixXf::Ones(p.rows(),1) * (p.col(1).sum() / p.rows()); - - //Normalize scale - p /= matrixToVector(p).norm(); - - //Normalize rotation - MatrixXf R = getRotation(referenceShape, p); - p = p * R; - - //Translate and scale into output space and store in output list - QList procrustesPoints; - for (int i = 0; i < p.rows(); i++) - procrustesPoints.append( QPointF( - (p(i, 0) - minX) / (maxX - minX) * (width - 1) + padding, - (p(i, 1) - minY) / (maxY - minY) * (qRound( width / aspectRatio) - 1) + padding)); - - dst = src; - dst.file.setList("ProcrustesPoints", procrustesPoints); - dst.file.set("ProcrustesBound", QRectF(0, 0, width + 2 * padding, (qRound(width / aspectRatio) + 2 * padding))); - dst.file.set("ProcrustesPadding", padding); - } - - void store(QDataStream &stream) const - { - stream << referenceShape; - stream << minX; - stream << minY; - stream << maxX; - stream << maxY; - stream << aspectRatio; - } - - void load(QDataStream &stream) - { - stream >> referenceShape; - stream >> minX; - stream >> minY; - stream >> maxX; - stream >> maxY; - stream >> aspectRatio; - } -}; - -BR_REGISTER(Transform, ProcrustesAlignTransform) - -/*! - * \ingroup transforms * \brief Creates a Delaunay triangulation based on a set of points * \author Scott Klum \cite sklum */ @@ -481,177 +283,6 @@ BR_REGISTER(Transform, DelaunayTransform) /*! * \ingroup transforms - * \brief Maps texture from one set of points to another. Assumes that points are rigidly transformed - * \author Brendan Klare \cite bklare - * \author Scott Klum \cite sklum - */ -class TextureMapTransform : public UntrainableTransform -{ - Q_OBJECT - - static QRectF getBounds(QList points, int dstPadding) { - float srcMinX = FLT_MAX; - float srcMinY = FLT_MAX; - float srcMaxX = -FLT_MAX; - float srcMaxY = -FLT_MAX; - for (int i = 0; i < points.size(); i++) { - if (points[i].x() < srcMinX) srcMinX = points[i].x(); - if (points[i].y() < srcMinY) srcMinY = points[i].y(); - if (points[i].x() > srcMaxX) srcMaxX = points[i].x(); - if (points[i].y() > srcMaxY) srcMaxY = points[i].y(); - } - - float padding = (srcMaxX - srcMinX) / 80 * dstPadding; - return QRectF(qRound(srcMinX - padding), qRound(srcMinY - padding), qRound(srcMaxX - srcMinX + 2 * padding), qRound(srcMaxY - srcMinY + 2 * padding)); - } - - static int getVertexIndex(QPointF trianglePts, QList pts) - { - for (int i = 0; i < pts.size(); i++) - if (trianglePts.x() == pts[i].x() && trianglePts.y() == pts[i].y()) - return i; - return -1; - } - - static QList addBounds(const QList _points, const QRectF bound) - { - QList points(_points); - points.append(bound.topLeft()); - points.append(QPointF(bound.right() - 1, bound.top())); - points.append(QPointF(bound.left(), bound.bottom() - 1)); - points.append(QPointF(bound.right() - 1, bound.bottom() - 1)); - return points; - } - - static QList > getTriangulation(const QList _points, const QRectF bound) - { - QList points(_points); - - Subdiv2D subdiv(OpenCVUtils::toRect(bound)); - for (int i = 0; i < points.size(); i++) - subdiv.insert(OpenCVUtils::toPoint(points[i])); - - vector triangleList; - subdiv.getTriangleList(triangleList); - - QList > triangleIndices; - for (size_t i = 0; i < triangleList.size(); i++) { - bool valid = true; - QList vertices; - vertices.append(QPointF(triangleList[i][0],triangleList[i][1])); - vertices.append(QPointF(triangleList[i][2],triangleList[i][3])); - vertices.append(QPointF(triangleList[i][4],triangleList[i][5])); - for (int j = 0; j < 3; j++) - if (vertices[j].x() > bound.right() || vertices[j].y() > bound.bottom() || vertices[j].x() < bound.left() || vertices[j].y() < bound.top()) - valid = false; - - if (valid) { - QList tri; - for (int j = 0; j < 3; j++) - tri.append(getVertexIndex(vertices[j], points)); - triangleIndices.append(tri); - } - } - - return triangleIndices; - } - - void project(const Template &src, Template &dst) const - { - QList dstPoints = dst.file.getList("ProcrustesPoints"); - QList srcPoints = dst.file.points(); - QRectF dstBound = dst.file.get("ProcrustesBound"); - QRectF srcBound = getBounds(srcPoints, dst.file.get("ProcrustesPadding")); - if (dstPoints.empty() || srcPoints.empty()) { - dst = src; - if (Globals->verbose) qWarning("Delauney triangulation failed because points or rects are empty."); - return; - } - - dstPoints = addBounds(dstPoints, dstBound); - srcPoints = addBounds(srcPoints, srcBound); - - QList > triIndices = getTriangulation(srcPoints, srcBound); - - int dstWidth = dstBound.width() + dstBound.x(); - int dstHeight = dstBound.height() + dstBound.y(); - dst.m() = Mat::zeros(dstHeight, dstWidth, src.m().type()); - for (int i = 0; i < triIndices.size(); i++) { - Point2f srcPoint1[3]; - Point2f dstPoint1[3]; - for (int j = 0; j < 3; j++) { - srcPoint1[j] = OpenCVUtils::toPoint(srcPoints[triIndices[i][j]]); - dstPoint1[j] = OpenCVUtils::toPoint(dstPoints[triIndices[i][j]]); - } - - Mat buffer(dstHeight, dstWidth, src.m().type()); - warpAffine(src.m(), buffer, getAffineTransform(srcPoint1, dstPoint1), Size(dstBound.width(), dstBound.height())); - - Mat mask = Mat::zeros(dstHeight, dstWidth, CV_8UC1); - Point maskPoints[1][3]; - maskPoints[0][0] = dstPoint1[0]; - maskPoints[0][1] = dstPoint1[1]; - maskPoints[0][2] = dstPoint1[2]; - const Point* ppt = { maskPoints[0] }; - fillConvexPoly(mask, ppt, 3, Scalar(255, 255, 255), 8); - - for (int i = 0; i < dstHeight; i++) { - for (int j = 0; j < dstWidth; j++) { - if (mask.at(i,j) == 255) { - if (dst.m().type() == CV_32FC3 || dst.m().type() == CV_8UC3) - dst.m().at(i,j) = buffer.at(i,j); - else if (dst.m().type() == CV_32F) - dst.m().at(i,j) = buffer.at(i,j); - else if (dst.m().type() == CV_8U) - dst.m().at(i,j) = buffer.at(i,j); - else - qFatal("Unsupported pixel format."); - } - } - } - - } - - dst.file.clearPoints(); - dst.file.clearRects(); - dst.file.setPoints(dstPoints); - } -}; - -BR_REGISTER(Transform, TextureMapTransform) - -/*! - * \ingroup initializers - * \brief Initialize Procrustes croppings - * \author Brendan Klare \cite bklare - */ -class ProcrustesInitializer : public Initializer -{ - Q_OBJECT - - void initialize() const - { - Globals->abbreviations.insert("ProcrustesStasmFace","ProcrustesAlign(padding=16)+TextureMap+Resize(48,48)"); - 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)"); - 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)"); - Globals->abbreviations.insert("ProcrustesStasmBrow","SelectPoints([16,17,18,19,20,21,22,23,24,25,26,27])+ProcrustesAlign(padding=8)+TextureMap+Resize(24,48)"); - Globals->abbreviations.insert("ProcrustesStasmNose","SelectPoints([48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58])+ProcrustesAlign(padding=8)+TextureMap+Resize(36,48)"); - 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)"); - Globals->abbreviations.insert("ProcrustesStasmJaw", "SelectPoints([2,3,4,5,6,7,8,9,10])+ProcrustesAlign(padding=8)+TextureMap+Resize(36,48)"); - - Globals->abbreviations.insert("ProcrustesLargeStasmFace","ProcrustesAlign(padding=16)+TextureMap+Resize(480,480)"); - 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)"); - 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)"); - Globals->abbreviations.insert("ProcrustesLargeStasmBrow","SelectPoints([16,17,18,19,20,21,22,23,24,25,26,27])+ProcrustesAlign(padding=8)+TextureMap+Resize(240,480)"); - Globals->abbreviations.insert("ProcrustesLargeStasmNose","SelectPoints([48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58])+ProcrustesAlign(padding=8)+TextureMap+Resize(360,480)"); - 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)"); - Globals->abbreviations.insert("ProcrustesLargeStasmJaw", "SelectPoints([2,3,4,5,6,7,8,9,10])+ProcrustesAlign(padding=8)+TextureMap+Resize(360,480)"); - } -}; -BR_REGISTER(Initializer, ProcrustesInitializer) - -/*! - * \ingroup transforms * \brief Creates a Delaunay triangulation based on a set of points * \author Scott Klum \cite sklum */ -- libgit2 0.21.4