Commit 9f84bcdb460ae5bb67bb10b5932e42296d4c0d50
1 parent
dd300435
project stable, still verifying accuracy
Showing
1 changed file
with
23 additions
and
49 deletions
openbr/plugins/landmarks.cpp
| @@ -150,16 +150,15 @@ class ProcrustesAlignTransform : public Transform | @@ -150,16 +150,15 @@ class ProcrustesAlignTransform : public Transform | ||
| 150 | 150 | ||
| 151 | Eigen::MatrixXf referenceShape; | 151 | Eigen::MatrixXf referenceShape; |
| 152 | 152 | ||
| 153 | - MatrixXf getRotation(MatrixXf ref, MatrixXf sample) { | 153 | + MatrixXf getRotation(MatrixXf ref, MatrixXf sample) const { |
| 154 | MatrixXf R = ref.transpose() * sample; | 154 | MatrixXf R = ref.transpose() * sample; |
| 155 | JacobiSVD<MatrixXf> svd(R, ComputeFullU | ComputeFullV); | 155 | JacobiSVD<MatrixXf> svd(R, ComputeFullU | ComputeFullV); |
| 156 | R = svd.matrixU() * svd.matrixV(); | 156 | R = svd.matrixU() * svd.matrixV(); |
| 157 | - | ||
| 158 | return R; | 157 | return R; |
| 159 | } | 158 | } |
| 160 | 159 | ||
| 161 | //Converts x y points in a single vector to two column matrix | 160 | //Converts x y points in a single vector to two column matrix |
| 162 | - MatrixXf vectorToMatrix(MatrixXf vector) { | 161 | + MatrixXf vectorToMatrix(MatrixXf vector) const { |
| 163 | int n = vector.rows(); | 162 | int n = vector.rows(); |
| 164 | MatrixXf matrix(n / 2, 2); | 163 | MatrixXf matrix(n / 2, 2); |
| 165 | for (int i = 0; i < n / 2; i++) { | 164 | for (int i = 0; i < n / 2; i++) { |
| @@ -170,7 +169,7 @@ class ProcrustesAlignTransform : public Transform | @@ -170,7 +169,7 @@ class ProcrustesAlignTransform : public Transform | ||
| 170 | return matrix; | 169 | return matrix; |
| 171 | } | 170 | } |
| 172 | 171 | ||
| 173 | - MatrixXf matrixToVector(MatrixXf matrix) { | 172 | + MatrixXf matrixToVector(MatrixXf matrix) const { |
| 174 | int n2 = matrix.rows(); | 173 | int n2 = matrix.rows(); |
| 175 | MatrixXf vector(n2 * 2, 1); | 174 | MatrixXf vector(n2 * 2, 1); |
| 176 | for (int i = 0; i < n2; i++) { | 175 | for (int i = 0; i < n2; i++) { |
| @@ -181,6 +180,7 @@ class ProcrustesAlignTransform : public Transform | @@ -181,6 +180,7 @@ class ProcrustesAlignTransform : public Transform | ||
| 181 | return vector; | 180 | return vector; |
| 182 | } | 181 | } |
| 183 | 182 | ||
| 183 | + | ||
| 184 | void train(const TemplateList &data) | 184 | void train(const TemplateList &data) |
| 185 | { | 185 | { |
| 186 | MatrixXf points(data[0].file.points().size() * 2, data.size()); | 186 | MatrixXf points(data[0].file.points().size() * 2, data.size()); |
| @@ -214,72 +214,46 @@ class ProcrustesAlignTransform : public Transform | @@ -214,72 +214,46 @@ class ProcrustesAlignTransform : public Transform | ||
| 214 | //Normalize rotation | 214 | //Normalize rotation |
| 215 | MatrixXf refPrev; | 215 | MatrixXf refPrev; |
| 216 | referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); | 216 | referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); |
| 217 | - float diff = FLT_MAX; | ||
| 218 | 217 | ||
| 219 | for (int j = 0; j < points.cols(); j++) { | 218 | for (int j = 0; j < points.cols(); j++) { |
| 220 | MatrixXf p = vectorToMatrix(points.col(j)); | 219 | MatrixXf p = vectorToMatrix(points.col(j)); |
| 221 | MatrixXf R = getRotation(referenceShape, p); | 220 | MatrixXf R = getRotation(referenceShape, p); |
| 222 | - p = p * R.transpose(); | 221 | + p = p * R; |
| 223 | points.col(j) = matrixToVector(p); | 222 | points.col(j) = matrixToVector(p); |
| 224 | } | 223 | } |
| 225 | 224 | ||
| 226 | referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); | 225 | referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); |
| 227 | } | 226 | } |
| 228 | 227 | ||
| 229 | - void procustesAlgin(const Template &src, Template &dst, MatrixXf p) { | ||
| 230 | 228 | ||
| 229 | + void project(const Template &src, Template &dst) const | ||
| 230 | + { | ||
| 231 | QList<QPointF> imagePoints = src.file.points(); | 231 | QList<QPointF> imagePoints = src.file.points(); |
| 232 | MatrixXf p(imagePoints.size() * 2, 1); | 232 | MatrixXf p(imagePoints.size() * 2, 1); |
| 233 | for (int i = 0; i < imagePoints.size(); i++) { | 233 | for (int i = 0; i < imagePoints.size(); i++) { |
| 234 | - | 234 | + p(i * 2) = imagePoints[i].x(); |
| 235 | + p(i * 2 + 1) = imagePoints[i].y(); | ||
| 235 | } | 236 | } |
| 236 | - } | 237 | + float norm = p.norm(); |
| 238 | + p = vectorToMatrix(p); | ||
| 237 | 239 | ||
| 238 | - void project(const Template &src, Template &dst) const | ||
| 239 | - { | ||
| 240 | - MatrixXf p(src.file.points().size() * 2, 1); | 240 | + //Nomralize translation |
| 241 | + p.col(0) = p.col(0) - MatrixXf::Ones(p.rows(),1) * (p.col(0).sum() / p.rows()); | ||
| 242 | + p.col(1) = p.col(1) - MatrixXf::Ones(p.rows(),1) * (p.col(1).sum() / p.rows()); | ||
| 241 | 243 | ||
| 242 | - | ||
| 243 | - // Normalize all sets of points | ||
| 244 | - for (int j = 0; j < data.size(); j++) { | ||
| 245 | - QList<QPointF> imagePoints = data[j].file.points(); | ||
| 246 | - | ||
| 247 | - float meanX = 0, | ||
| 248 | - meanY = 0; | ||
| 249 | - for (int i = 0; i < imagepoints.size(); i++) { | ||
| 250 | - points(i * 2, j) = imagepoints[i].x(); | ||
| 251 | - points(i * 2 + 1, j) = imagepoints[i].y(); | ||
| 252 | - meanX += imagePoints[i].x(); | ||
| 253 | - meanY += imagePoints[i].y(); | ||
| 254 | - } | ||
| 255 | - meanX /= imagePoints.size(); | ||
| 256 | - meanY /= imagePoints.size(); | ||
| 257 | - | ||
| 258 | - for (int i = 0; i < imagePoints.size(); i++) { | ||
| 259 | - points(i * 2, j) -= meanX; | ||
| 260 | - points(i * 2 + 1, j) -= meanY; | ||
| 261 | - } | ||
| 262 | - } | ||
| 263 | - | ||
| 264 | - | ||
| 265 | - //normalize scale | ||
| 266 | - for (int i = 0; i < points.cols(); i++) | ||
| 267 | - points.col(i) = points.col(i) / points.col(i).norm(); | 244 | + //Normalize scale |
| 245 | + p /= norm; | ||
| 268 | 246 | ||
| 269 | //Normalize rotation | 247 | //Normalize rotation |
| 270 | - MatrixXf refPrev; | ||
| 271 | - referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); | ||
| 272 | - float diff = FLT_MAX; | ||
| 273 | - | ||
| 274 | - for (int j = 0; j < points.cols(); j++) { | ||
| 275 | - MatrixXf p = vectorToMatrix(points.col(j)); | ||
| 276 | - MatrixXf R = getRotation(referenceShape, p); | ||
| 277 | - p = p * R.transpose(); | ||
| 278 | - points.col(j) = matrixToVector(p); | ||
| 279 | - } | 248 | + MatrixXf R = getRotation(referenceShape, p); |
| 249 | + p = p * R; | ||
| 280 | 250 | ||
| 281 | - referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); | 251 | + QList<QPointF> procrustesPoints; |
| 252 | + for (int i = 0; i < p.rows(); i++) | ||
| 253 | + procrustesPoints.append(QPointF(p(i, 0), p(i, 1))); | ||
| 282 | 254 | ||
| 255 | + dst = src; | ||
| 256 | + dst.file.setList<QPointF>("ProcrustesPoints", procrustesPoints); | ||
| 283 | } | 257 | } |
| 284 | 258 | ||
| 285 | void store(QDataStream &stream) const | 259 | void store(QDataStream &stream) const |