Commit 6c39964869c22dfbc3f7251fd128ceeb4ea5c017

Authored by Brendan K
2 parents eb77145e 39a41bb0

Merge pull request #229 from biometrics/AffineRestore

Transform to map stasm points back into original coordinate space
openbr/core/eigenutils.cpp
... ... @@ -77,7 +77,7 @@ float eigStd(const Eigen::MatrixXf& x) {
77 77 return sqrt((x.array() - mean).pow(2).sum() / (x.cols() * x.rows()));
78 78 }
79 79  
80   -MatrixXf removeRowCol(MatrixXf X, int row, int col) {
  80 +MatrixXf removeRowCol(const MatrixXf X, int row, int col) {
81 81 MatrixXf Y(X.rows() - 1,X.cols() - 1);
82 82  
83 83 for (int i1 = 0, i2 = 0; i1 < X.rows(); i1++) {
... ... @@ -96,11 +96,44 @@ MatrixXf removeRowCol(MatrixXf X, int row, int col) {
96 96 return Y;
97 97 }
98 98  
99   -MatrixXf pointsToMatrix(QList<QPointF> points) {
100   - MatrixXf P(points.size(), 2);
  99 +MatrixXf pointsToMatrix(const QList<QPointF> points, bool isAffine) {
  100 + MatrixXf P(points.size(), isAffine ? 3 : 2);
101 101 for (int i = 0; i < points.size(); i++) {
102 102 P(i, 0) = points[i].x();
103 103 P(i, 1) = points[i].y();
  104 + if (isAffine)
  105 + P(i, 2) = 1;
104 106 }
105 107 return P;
106 108 }
  109 +
  110 +QList<QPointF> matrixToPoints(const Eigen::MatrixXf P) {
  111 + QList<QPointF> points;
  112 + for (int i = 0; i < P.rows(); i++)
  113 + points.append(QPointF(P(i, 0), P(i, 1)));
  114 + return points;
  115 +}
  116 +
  117 +//Converts x y points in a single vector to two column matrix
  118 +Eigen::MatrixXf vectorToMatrix(const Eigen::MatrixXf vector) {
  119 + int n = vector.rows();
  120 + Eigen::MatrixXf matrix(n / 2, 2);
  121 + for (int i = 0; i < n / 2; i++) {
  122 + for (int j = 0; j < 2; j++) {
  123 + matrix(i, j) = vector(i * 2 + j);
  124 + }
  125 + }
  126 + return matrix;
  127 +}
  128 +
  129 +Eigen::MatrixXf matrixToVector(const Eigen::MatrixXf matrix) {
  130 + int n2 = matrix.rows();
  131 + Eigen::MatrixXf vector(n2 * 2, 1);
  132 + for (int i = 0; i < n2; i++) {
  133 + for (int j = 0; j < 2; j++) {
  134 + vector(i * 2 + j) = matrix(i, j);
  135 + }
  136 + }
  137 + return vector;
  138 +}
  139 +
... ...
openbr/core/eigenutils.h
... ... @@ -29,12 +29,16 @@ void printEigen(Eigen::MatrixXd X);
29 29 void printEigen(Eigen::MatrixXf X);
30 30 void printSize(Eigen::MatrixXf X);
31 31  
  32 +//Converts x y points in a single vector to two column matrix
  33 +Eigen::MatrixXf vectorToMatrix(const Eigen::MatrixXf vector);
  34 +Eigen::MatrixXf matrixToVector(const Eigen::MatrixXf matrix);
  35 +
32 36 //Remove row and column from the matrix:
33   -Eigen::MatrixXf removeRowCol(Eigen::MatrixXf X, int row, int col);
  37 +Eigen::MatrixXf removeRowCol(const Eigen::MatrixXf X, int row, int col);
34 38  
35 39 //Convert a point list into a matrix:
36   -Eigen::MatrixXf pointsToMatrix(QList<QPointF> points);
37   -
  40 +Eigen::MatrixXf pointsToMatrix(const QList<QPointF> points, bool isAffine=false);
  41 +QList<QPointF> matrixToPoints(const Eigen::MatrixXf P);
38 42  
39 43 template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
40 44 inline QDataStream &operator<<(QDataStream &stream, const Eigen::Matrix< _Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols > &mat)
... ...
openbr/plugins/draw.cpp
... ... @@ -553,7 +553,7 @@ class WriteImageTransform : public TimeVaryingTransform
553 553 void projectUpdate(const Template &src, Template &dst)
554 554 {
555 555 dst = src;
556   - OpenCVUtils::saveImage(dst.m(), QString("%1/%2_%3.%4").arg(outputDirectory).arg(imageName).arg(cnt++, 5, QChar('0')).arg(imgExtension));
  556 + OpenCVUtils::saveImage(dst.m(), QString("%1/%2_%3.%4").arg(outputDirectory).arg(imageName).arg(cnt++, 5, 10, QChar('0')).arg(imgExtension));
557 557 }
558 558  
559 559 };
... ...
openbr/plugins/register.cpp
... ... @@ -53,6 +53,7 @@ private:
53 53 Q_PROPERTY(float x3 READ get_x3 WRITE set_x3 RESET reset_x3 STORED false)
54 54 Q_PROPERTY(float y3 READ get_y3 WRITE set_y3 RESET reset_y3 STORED false)
55 55 Q_PROPERTY(Method method READ get_method WRITE set_method RESET reset_method STORED false)
  56 + Q_PROPERTY(bool storeAffine READ get_storeAffine WRITE set_storeAffine RESET reset_storeAffine STORED false)
56 57 BR_PROPERTY(int, width, 64)
57 58 BR_PROPERTY(int, height, 64)
58 59 BR_PROPERTY(float, x1, 0)
... ... @@ -62,6 +63,7 @@ private:
62 63 BR_PROPERTY(float, x3, -1)
63 64 BR_PROPERTY(float, y3, -1)
64 65 BR_PROPERTY(Method, method, Bilin)
  66 + BR_PROPERTY(bool, storeAffine, false)
65 67  
66 68 static Point2f getThirdAffinePoint(const Point2f &a, const Point2f &b)
67 69 {
... ... @@ -105,10 +107,17 @@ private:
105 107 }
106 108 if (twoPoints) srcPoints[2] = getThirdAffinePoint(srcPoints[0], srcPoints[1]);
107 109  
108   - warpAffine(src, dst, getAffineTransform(srcPoints, dstPoints), Size(width, height), method);
  110 + Mat affineTransform = getAffineTransform(srcPoints, dstPoints);
  111 + warpAffine(src, dst, affineTransform, Size(width, height), method);
  112 + if (storeAffine) {
  113 + QList<float> affineParams;
  114 + for (int i = 0 ; i < 2; i++)
  115 + for (int j = 0; j < 3; j++)
  116 + affineParams.append(affineTransform.at<double>(i, j));
  117 + dst.file.setList("affineParameters", affineParams);
  118 + }
109 119 }
110 120 };
111   -
112 121 BR_REGISTER(Transform, AffineTransform)
113 122  
114 123 /*!
... ...
openbr/plugins/stasm4.cpp
1 1 #include <stasm_lib.h>
2 2 #include <stasmcascadeclassifier.h>
3 3 #include <opencv2/opencv.hpp>
  4 +#include <Eigen/Dense>
4 5 #include "openbr_internal.h"
5 6 #include "openbr/core/qtutils.h"
6 7 #include "openbr/core/opencvutils.h"
  8 +#include "openbr/core/eigenutils.h"
7 9 #include <QString>
8 10  
9 11 using namespace std;
... ... @@ -160,6 +162,41 @@ class StasmTransform : public UntrainableTransform
160 162  
161 163 BR_REGISTER(Transform, StasmTransform)
162 164  
  165 +/*!
  166 + * \ingroup transforms
  167 + * \brief Designed for use after eye detection + Stasm, this will
  168 + * revert the detected landmarks to the original coordinate space
  169 + * before affine alignment to the stasm mean shape. The storeTransform
  170 + * parameter must be set to true when calling AffineTransform before this.
  171 + * \author Brendan Klare \cite bklare
  172 + */
  173 +class RevertAffineTransform : public UntrainableTransform
  174 +{
  175 + Q_OBJECT
  176 +
  177 +private:
  178 +
  179 + void project(const Template &src, Template &dst) const
  180 + {
  181 + QList<float> paramList = src.file.getList<float>("affineParameters");
  182 + Eigen::MatrixXf points = pointsToMatrix(src.file.points(), true);
  183 + Eigen::MatrixXf affine = Eigen::MatrixXf::Zero(3, 3);
  184 + for (int i = 0, cnt = 0; i < 2; i++)
  185 + for (int j = 0; j < 3; j++, cnt++)
  186 + affine(i, j) = paramList[cnt];
  187 + affine(2, 2) = 1;
  188 + affine = affine.inverse();
  189 + Eigen::MatrixXf affineInv = affine.block(0, 0, 2, 3);
  190 + Eigen::MatrixXf pointsT = points.transpose();
  191 + points = affineInv * pointsT;
  192 + dst = src;
  193 + dst.file.clearPoints();
  194 + dst.file.setPoints(matrixToPoints(points.transpose()));
  195 + }
  196 +};
  197 +
  198 +BR_REGISTER(Transform, RevertAffineTransform)
  199 +
163 200 } // namespace br
164 201  
165 202 #include "stasm4.moc"
... ...