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 | 150 | |
| 151 | 151 | Eigen::MatrixXf referenceShape; |
| 152 | 152 | |
| 153 | - MatrixXf getRotation(MatrixXf ref, MatrixXf sample) { | |
| 153 | + MatrixXf getRotation(MatrixXf ref, MatrixXf sample) const { | |
| 154 | 154 | MatrixXf R = ref.transpose() * sample; |
| 155 | 155 | JacobiSVD<MatrixXf> svd(R, ComputeFullU | ComputeFullV); |
| 156 | 156 | R = svd.matrixU() * svd.matrixV(); |
| 157 | - | |
| 158 | 157 | return R; |
| 159 | 158 | } |
| 160 | 159 | |
| 161 | 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 | 162 | int n = vector.rows(); |
| 164 | 163 | MatrixXf matrix(n / 2, 2); |
| 165 | 164 | for (int i = 0; i < n / 2; i++) { |
| ... | ... | @@ -170,7 +169,7 @@ class ProcrustesAlignTransform : public Transform |
| 170 | 169 | return matrix; |
| 171 | 170 | } |
| 172 | 171 | |
| 173 | - MatrixXf matrixToVector(MatrixXf matrix) { | |
| 172 | + MatrixXf matrixToVector(MatrixXf matrix) const { | |
| 174 | 173 | int n2 = matrix.rows(); |
| 175 | 174 | MatrixXf vector(n2 * 2, 1); |
| 176 | 175 | for (int i = 0; i < n2; i++) { |
| ... | ... | @@ -181,6 +180,7 @@ class ProcrustesAlignTransform : public Transform |
| 181 | 180 | return vector; |
| 182 | 181 | } |
| 183 | 182 | |
| 183 | + | |
| 184 | 184 | void train(const TemplateList &data) |
| 185 | 185 | { |
| 186 | 186 | MatrixXf points(data[0].file.points().size() * 2, data.size()); |
| ... | ... | @@ -214,72 +214,46 @@ class ProcrustesAlignTransform : public Transform |
| 214 | 214 | //Normalize rotation |
| 215 | 215 | MatrixXf refPrev; |
| 216 | 216 | referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); |
| 217 | - float diff = FLT_MAX; | |
| 218 | 217 | |
| 219 | 218 | for (int j = 0; j < points.cols(); j++) { |
| 220 | 219 | MatrixXf p = vectorToMatrix(points.col(j)); |
| 221 | 220 | MatrixXf R = getRotation(referenceShape, p); |
| 222 | - p = p * R.transpose(); | |
| 221 | + p = p * R; | |
| 223 | 222 | points.col(j) = matrixToVector(p); |
| 224 | 223 | } |
| 225 | 224 | |
| 226 | 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 | 231 | QList<QPointF> imagePoints = src.file.points(); |
| 232 | 232 | MatrixXf p(imagePoints.size() * 2, 1); |
| 233 | 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 | 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 | 259 | void store(QDataStream &stream) const | ... | ... |