Commit 4261d8e6a1050c7c68bf50719350524c354511c4
1 parent
9f84bcdb
Finalized procrustes training and alignment
Showing
1 changed file
with
66 additions
and
15 deletions
openbr/plugins/landmarks.cpp
| ... | ... | @@ -146,9 +146,24 @@ class ProcrustesAlignTransform : public Transform |
| 146 | 146 | Q_OBJECT |
| 147 | 147 | |
| 148 | 148 | Q_PROPERTY(float width READ get_width WRITE set_width RESET reset_width STORED false) |
| 149 | - BR_PROPERTY(float, width, true) | |
| 149 | + Q_PROPERTY(float padding READ get_padding WRITE set_padding RESET reset_padding STORED false) | |
| 150 | + BR_PROPERTY(float, width, 80) | |
| 151 | + BR_PROPERTY(float, padding, 8) | |
| 150 | 152 | |
| 151 | 153 | Eigen::MatrixXf referenceShape; |
| 154 | + float minX; | |
| 155 | + float minY; | |
| 156 | + float maxX; | |
| 157 | + float maxY; | |
| 158 | + float aspectRatio; | |
| 159 | + | |
| 160 | + void init() { | |
| 161 | + minX = FLT_MAX, | |
| 162 | + minY = FLT_MAX, | |
| 163 | + maxX = -FLT_MAX, | |
| 164 | + maxY = -FLT_MAX; | |
| 165 | + aspectRatio = 0; | |
| 166 | + } | |
| 152 | 167 | |
| 153 | 168 | MatrixXf getRotation(MatrixXf ref, MatrixXf sample) const { |
| 154 | 169 | MatrixXf R = ref.transpose() * sample; |
| ... | ... | @@ -180,7 +195,6 @@ class ProcrustesAlignTransform : public Transform |
| 180 | 195 | return vector; |
| 181 | 196 | } |
| 182 | 197 | |
| 183 | - | |
| 184 | 198 | void train(const TemplateList &data) |
| 185 | 199 | { |
| 186 | 200 | MatrixXf points(data[0].file.points().size() * 2, data.size()); |
| ... | ... | @@ -206,7 +220,6 @@ class ProcrustesAlignTransform : public Transform |
| 206 | 220 | } |
| 207 | 221 | } |
| 208 | 222 | |
| 209 | - | |
| 210 | 223 | //normalize scale |
| 211 | 224 | for (int i = 0; i < points.cols(); i++) |
| 212 | 225 | points.col(i) = points.col(i) / points.col(i).norm(); |
| ... | ... | @@ -214,17 +227,40 @@ class ProcrustesAlignTransform : public Transform |
| 214 | 227 | //Normalize rotation |
| 215 | 228 | MatrixXf refPrev; |
| 216 | 229 | referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); |
| 217 | - | |
| 218 | - for (int j = 0; j < points.cols(); j++) { | |
| 219 | - MatrixXf p = vectorToMatrix(points.col(j)); | |
| 220 | - MatrixXf R = getRotation(referenceShape, p); | |
| 221 | - p = p * R; | |
| 222 | - points.col(j) = matrixToVector(p); | |
| 230 | + float diff = FLT_MAX; | |
| 231 | + while (diff > 1e-5) {//iterate until reference shape is stable | |
| 232 | + refPrev = referenceShape; | |
| 233 | + | |
| 234 | + for (int j = 0; j < points.cols(); j++) { | |
| 235 | + MatrixXf p = vectorToMatrix(points.col(j)); | |
| 236 | + MatrixXf R = getRotation(referenceShape, p); | |
| 237 | + p = p * R.transpose(); | |
| 238 | + points.col(j) = matrixToVector(p); | |
| 239 | + } | |
| 240 | + referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); | |
| 241 | + diff = (matrixToVector(referenceShape) - matrixToVector(refPrev)).norm(); | |
| 223 | 242 | } |
| 224 | 243 | |
| 225 | 244 | referenceShape = vectorToMatrix(points.rowwise().sum() / points.cols()); |
| 226 | - } | |
| 227 | 245 | |
| 246 | + //Choose crop boundaries and adjustments that captures all data | |
| 247 | + for (int i = 0; i < points.rows(); i++) { | |
| 248 | + for (int j = 0; j < points.cols(); j++) { | |
| 249 | + if (i % 2 == 0) { | |
| 250 | + if (points(i,j) > maxX) | |
| 251 | + maxX = points(i, j); | |
| 252 | + if (points(i,j) < minX) | |
| 253 | + minX = points(i, j); | |
| 254 | + } else { | |
| 255 | + if (points(i,j) > maxY) | |
| 256 | + maxY = points(i, j); | |
| 257 | + if (points(i,j) < minY) | |
| 258 | + minY = points(i, j); | |
| 259 | + } | |
| 260 | + } | |
| 261 | + } | |
| 262 | + aspectRatio = (maxX - minX) / (maxY - minY); | |
| 263 | + } | |
| 228 | 264 | |
| 229 | 265 | void project(const Template &src, Template &dst) const |
| 230 | 266 | { |
| ... | ... | @@ -234,7 +270,6 @@ class ProcrustesAlignTransform : public Transform |
| 234 | 270 | p(i * 2) = imagePoints[i].x(); |
| 235 | 271 | p(i * 2 + 1) = imagePoints[i].y(); |
| 236 | 272 | } |
| 237 | - float norm = p.norm(); | |
| 238 | 273 | p = vectorToMatrix(p); |
| 239 | 274 | |
| 240 | 275 | //Nomralize translation |
| ... | ... | @@ -242,30 +277,46 @@ class ProcrustesAlignTransform : public Transform |
| 242 | 277 | p.col(1) = p.col(1) - MatrixXf::Ones(p.rows(),1) * (p.col(1).sum() / p.rows()); |
| 243 | 278 | |
| 244 | 279 | //Normalize scale |
| 245 | - p /= norm; | |
| 280 | + p /= matrixToVector(p).norm(); | |
| 246 | 281 | |
| 247 | 282 | //Normalize rotation |
| 248 | 283 | MatrixXf R = getRotation(referenceShape, p); |
| 249 | - p = p * R; | |
| 284 | + p = p * R.transpose(); | |
| 250 | 285 | |
| 286 | + for (int i = 0; i < p.rows(); i++) { | |
| 287 | + } | |
| 288 | + | |
| 289 | + //Translate and scale into output space and store in output list | |
| 251 | 290 | QList<QPointF> procrustesPoints; |
| 252 | 291 | for (int i = 0; i < p.rows(); i++) |
| 253 | - procrustesPoints.append(QPointF(p(i, 0), p(i, 1))); | |
| 292 | + procrustesPoints.append( QPointF( | |
| 293 | + (p(i, 0) - minX) / (maxX - minX) * (width - 1) + padding, | |
| 294 | + (p(i, 1) - minY) / (maxY - minY) * (qRound( width / aspectRatio) - 1) + padding)); | |
| 254 | 295 | |
| 255 | 296 | dst = src; |
| 256 | 297 | dst.file.setList<QPointF>("ProcrustesPoints", procrustesPoints); |
| 298 | + dst.file.set("ProcrustesBound", QRectF(0, 0, width + 2 * padding, (qRound(width / aspectRatio) + 2 * padding))); | |
| 257 | 299 | } |
| 258 | 300 | |
| 259 | 301 | void store(QDataStream &stream) const |
| 260 | 302 | { |
| 261 | 303 | stream << referenceShape; |
| 304 | + stream << minX; | |
| 305 | + stream << minY; | |
| 306 | + stream << maxX; | |
| 307 | + stream << maxY; | |
| 308 | + stream << aspectRatio; | |
| 262 | 309 | } |
| 263 | 310 | |
| 264 | 311 | void load(QDataStream &stream) |
| 265 | 312 | { |
| 266 | 313 | stream >> referenceShape; |
| 314 | + stream >> minX; | |
| 315 | + stream >> minY; | |
| 316 | + stream >> maxX; | |
| 317 | + stream >> maxY; | |
| 318 | + stream >> aspectRatio; | |
| 267 | 319 | } |
| 268 | - | |
| 269 | 320 | }; |
| 270 | 321 | |
| 271 | 322 | BR_REGISTER(Transform, ProcrustesAlignTransform) | ... | ... |