Commit 8efb2824c2ac475dfe98f73ddafa78825c313c88
1 parent
274b7ff1
updated CT8 to use new template metadata API, cleaned up some of the logic
Showing
1 changed file
with
37 additions
and
61 deletions
sdk/plugins/ct8.cpp
| @@ -236,7 +236,6 @@ struct CT8Context | @@ -236,7 +236,6 @@ struct CT8Context | ||
| 236 | FRsdk::SampleSet sampleSet; | 236 | FRsdk::SampleSet sampleSet; |
| 237 | sampleSet.push_back(sample); | 237 | sampleSet.push_back(sample); |
| 238 | 238 | ||
| 239 | - | ||
| 240 | FRsdk::EnrolOpenCVFeedback * feedback_body = new FRsdk::EnrolOpenCVFeedback(m); | 239 | FRsdk::EnrolOpenCVFeedback * feedback_body = new FRsdk::EnrolOpenCVFeedback(m); |
| 241 | FRsdk::CountedPtr<FRsdk::Enrollment::FeedbackBody> feedback_ptr(feedback_body); | 240 | FRsdk::CountedPtr<FRsdk::Enrollment::FeedbackBody> feedback_ptr(feedback_body); |
| 242 | 241 | ||
| @@ -300,14 +299,14 @@ protected: | @@ -300,14 +299,14 @@ protected: | ||
| 300 | * \author Josh Klontz \cite jklontz | 299 | * \author Josh Klontz \cite jklontz |
| 301 | * \author Charles Otto \cite caotto | 300 | * \author Charles Otto \cite caotto |
| 302 | */ | 301 | */ |
| 303 | -struct CT8Detect : public UntrainableTransform | ||
| 304 | - , public CT8Context | 302 | +class CT8DetectTransform : public UntrainableTransform |
| 303 | + , public CT8Context | ||
| 305 | { | 304 | { |
| 306 | -public: | ||
| 307 | Q_OBJECT | 305 | Q_OBJECT |
| 308 | - | ||
| 309 | Q_PROPERTY(float minRelEyeDistance READ get_minRelEyeDistance WRITE set_minRelEyeDistance RESET reset_minRelEyeDistance STORED false) | 306 | Q_PROPERTY(float minRelEyeDistance READ get_minRelEyeDistance WRITE set_minRelEyeDistance RESET reset_minRelEyeDistance STORED false) |
| 310 | Q_PROPERTY(float maxRelEyeDistance READ get_maxRelEyeDistance WRITE set_maxRelEyeDistance RESET reset_maxRelEyeDistance STORED false) | 307 | Q_PROPERTY(float maxRelEyeDistance READ get_maxRelEyeDistance WRITE set_maxRelEyeDistance RESET reset_maxRelEyeDistance STORED false) |
| 308 | + BR_PROPERTY(float, minRelEyeDistance, 0.01f) | ||
| 309 | + BR_PROPERTY(float, maxRelEyeDistance, 0.4f) | ||
| 311 | 310 | ||
| 312 | // Perform face, then eye detection using the facevacs SDK | 311 | // Perform face, then eye detection using the facevacs SDK |
| 313 | void project(const Template &src, Template &dst) const | 312 | void project(const Template &src, Template &dst) const |
| @@ -316,57 +315,39 @@ public: | @@ -316,57 +315,39 @@ public: | ||
| 316 | // Build an FRsdk image from the input openCV mat | 315 | // Build an FRsdk image from the input openCV mat |
| 317 | FRsdk::CountedPtr<FRsdk::ImageBody> i(new FRsdk::OpenCVImageBody(src)); | 316 | FRsdk::CountedPtr<FRsdk::ImageBody> i(new FRsdk::OpenCVImageBody(src)); |
| 318 | FRsdk::Image img(i); | 317 | FRsdk::Image img(i); |
| 319 | - | ||
| 320 | FRsdk::Face::LocationSet faceLocations = faceFinder->find(img, minRelEyeDistance, maxRelEyeDistance); | 318 | FRsdk::Face::LocationSet faceLocations = faceFinder->find(img, minRelEyeDistance, maxRelEyeDistance); |
| 321 | - | ||
| 322 | - // If the face finder doesn't find anything mark the output as a failure | ||
| 323 | - if (faceLocations.empty() ) { | ||
| 324 | - dst.file.setBool("FTE"); | ||
| 325 | - return; | ||
| 326 | - } | ||
| 327 | - | ||
| 328 | - QList<QRectF> ROIs; | ||
| 329 | - QList<QPointF> landmarks; | ||
| 330 | - FRsdk::Face::LocationSet::const_iterator faceLocationSetIterator = faceLocations.begin(); | ||
| 331 | - bool any_eyes = false; | ||
| 332 | 319 | ||
| 333 | // Attempt to detect eyes in any face ROIs that were detected | 320 | // Attempt to detect eyes in any face ROIs that were detected |
| 321 | + QList<QRectF> rects; | ||
| 322 | + QList<QPointF> points; | ||
| 323 | + FRsdk::Face::LocationSet::const_iterator faceLocationSetIterator = faceLocations.begin(); | ||
| 334 | while (faceLocationSetIterator != faceLocations.end()) { | 324 | while (faceLocationSetIterator != faceLocations.end()) { |
| 335 | FRsdk::Face::Location faceLocation = *faceLocationSetIterator; faceLocationSetIterator++; | 325 | FRsdk::Face::Location faceLocation = *faceLocationSetIterator; faceLocationSetIterator++; |
| 336 | FRsdk::Eyes::LocationSet currentEyesLocations = eyesFinder->find(img, faceLocation); | 326 | FRsdk::Eyes::LocationSet currentEyesLocations = eyesFinder->find(img, faceLocation); |
| 337 | 327 | ||
| 338 | if (currentEyesLocations.size() > 0) { | 328 | if (currentEyesLocations.size() > 0) { |
| 339 | - any_eyes = true; | ||
| 340 | - ROIs.append(QRectF(faceLocation.pos.x(), faceLocation.pos.y(), faceLocation.width, faceLocation.width)); | ||
| 341 | - landmarks.append(QPointF(currentEyesLocations.front().first.x(), currentEyesLocations.front().first.y())); | ||
| 342 | - landmarks.append(QPointF(currentEyesLocations.front().second.x(), currentEyesLocations.front().second.y())); | ||
| 343 | - | ||
| 344 | - dst += src; | 329 | + rects.append(QRectF(faceLocation.pos.x(), faceLocation.pos.y(), faceLocation.width, faceLocation.width)); |
| 330 | + points.append(QPointF(currentEyesLocations.front().first.x(), currentEyesLocations.front().first.y())); | ||
| 331 | + points.append(QPointF(currentEyesLocations.front().second.x(), currentEyesLocations.front().second.y())); | ||
| 332 | + dst += src.m(); | ||
| 333 | + if (!Globals->enrollAll) break; | ||
| 345 | } | 334 | } |
| 346 | - | ||
| 347 | - if (any_eyes && !Globals->enrollAll && !dst.isEmpty()) break; | ||
| 348 | } | 335 | } |
| 349 | 336 | ||
| 350 | // If eye detection failed, mark the output as a failure | 337 | // If eye detection failed, mark the output as a failure |
| 351 | - if (!any_eyes) { | ||
| 352 | - dst.file.setBool("FTE"); | ||
| 353 | - return; | 338 | + if (dst.isEmpty()) { |
| 339 | + dst.file.set("FTE", true); | ||
| 340 | + if (!Globals->enrollAll) dst += Mat(); | ||
| 354 | } | 341 | } |
| 355 | - | ||
| 356 | - dst.file.setROIs(ROIs); | ||
| 357 | - dst.file.setLandmarks(landmarks); | 342 | + dst.file.appendRects(rects); |
| 343 | + dst.file.appendPoints(points); | ||
| 358 | } catch (std::exception &e) { | 344 | } catch (std::exception &e) { |
| 359 | qFatal("CT8Enroll Exception: %s", e.what()); | 345 | qFatal("CT8Enroll Exception: %s", e.what()); |
| 360 | } | 346 | } |
| 361 | - | ||
| 362 | - if (!Globals->enrollAll && dst.isEmpty()) dst += Mat(); | ||
| 363 | - } | ||
| 364 | -private: | ||
| 365 | - BR_PROPERTY(float, minRelEyeDistance, 0.01f) | ||
| 366 | - BR_PROPERTY(float, maxRelEyeDistance, 0.4f) | 347 | + } |
| 367 | }; | 348 | }; |
| 368 | 349 | ||
| 369 | -BR_REGISTER(Transform, CT8Detect) | 350 | +BR_REGISTER(Transform, CT8DetectTransform) |
| 370 | 351 | ||
| 371 | /*! | 352 | /*! |
| 372 | * \ingroup transforms | 353 | * \ingroup transforms |
| @@ -374,10 +355,11 @@ BR_REGISTER(Transform, CT8Detect) | @@ -374,10 +355,11 @@ BR_REGISTER(Transform, CT8Detect) | ||
| 374 | * \author Josh Klontz \cite jklontz | 355 | * \author Josh Klontz \cite jklontz |
| 375 | * \author Charles Otto \cite caotto | 356 | * \author Charles Otto \cite caotto |
| 376 | */ | 357 | */ |
| 377 | -struct CT8Enroll : public UntrainableTransform | ||
| 378 | - , public CT8Context | 358 | +class CT8EnrollTransform : public UntrainableTransform |
| 359 | + , public CT8Context | ||
| 379 | { | 360 | { |
| 380 | Q_OBJECT | 361 | Q_OBJECT |
| 362 | + | ||
| 381 | // enroll an image using the facevacs sdk. Generates a facevacs "fir" which | 363 | // enroll an image using the facevacs sdk. Generates a facevacs "fir" which |
| 382 | // is their face representation. | 364 | // is their face representation. |
| 383 | void project(const Template &src, Template &dst) const | 365 | void project(const Template &src, Template &dst) const |
| @@ -387,37 +369,31 @@ struct CT8Enroll : public UntrainableTransform | @@ -387,37 +369,31 @@ struct CT8Enroll : public UntrainableTransform | ||
| 387 | FRsdk::Image img(i); | 369 | FRsdk::Image img(i); |
| 388 | 370 | ||
| 389 | // If we already have eye locations, use them | 371 | // If we already have eye locations, use them |
| 390 | - QList<QPointF> landmarks = src.file.landmarks(); | ||
| 391 | - bool enroll_succeeded = false; | ||
| 392 | - if (landmarks.size() == 2) { | ||
| 393 | - enroll_succeeded = enroll(img, FRsdk::Eyes::Location(toPosition(landmarks[0]), toPosition(landmarks[1])), &(dst.m())); | 372 | + QList<QPointF> points = src.file.points(); |
| 373 | + bool enrollSucceeded = false; | ||
| 374 | + if (points.size() == 2) { | ||
| 375 | + enrollSucceeded = enroll(img, FRsdk::Eyes::Location(toPosition(points[0]), toPosition(points[1])), &(dst.m())); | ||
| 394 | 376 | ||
| 395 | // Transfer previously detectd eye and face locations to the output dst. | 377 | // Transfer previously detectd eye and face locations to the output dst. |
| 396 | - dst.file.insert("CT8_First_Eye_X", landmarks[0].x()); | ||
| 397 | - dst.file.insert("CT8_First_Eye_Y", landmarks[0].y()); | ||
| 398 | - dst.file.insert("CT8_Second_Eye_X", landmarks[1].x()); | ||
| 399 | - dst.file.insert("CT8_Second_Eye_Y", landmarks[1].y()); | ||
| 400 | - | ||
| 401 | - QList<QRectF> ROIs = src.file.ROIs(); | ||
| 402 | - if (ROIs.size() == 1) { | ||
| 403 | - dst.file.insert("CT8_Face_X", ROIs.first().x()); | ||
| 404 | - dst.file.insert("CT8_Face_Y", ROIs.first().y()); | ||
| 405 | - dst.file.insert("CT8_Face_Width", ROIs.first().width()); | ||
| 406 | - dst.file.insert("CT8_Face_Height", ROIs.first().height()); | ||
| 407 | - } | 378 | + dst.file.set("First_Eye", points[0]); |
| 379 | + dst.file.set("Second_Eye", points[1]); | ||
| 380 | + | ||
| 381 | + QList<QRectF> rects = src.file.rects(); | ||
| 382 | + if (rects.size() == 1) | ||
| 383 | + dst.file.set("Face", rects.first()); | ||
| 408 | } else { | 384 | } else { |
| 409 | // If we don't have eye locations already, calling enroll here | 385 | // If we don't have eye locations already, calling enroll here |
| 410 | // will cause facevacs to perform detection using default | 386 | // will cause facevacs to perform detection using default |
| 411 | // parameters (and we will not receive the detected locations | 387 | // parameters (and we will not receive the detected locations |
| 412 | // as output). | 388 | // as output). |
| 413 | - enroll_succeeded = enroll(img, &(dst.m())); | 389 | + enrollSucceeded = enroll(img, &(dst.m())); |
| 414 | } | 390 | } |
| 391 | + | ||
| 415 | // If enrollment failed, mark this image as a failure. This will | 392 | // If enrollment failed, mark this image as a failure. This will |
| 416 | // typically only happen if we aren't using pre-detected eye | 393 | // typically only happen if we aren't using pre-detected eye |
| 417 | // locations | 394 | // locations |
| 418 | - if (!enroll_succeeded) | ||
| 419 | - { | ||
| 420 | - dst.file.setBool("FTE"); | 395 | + if (!enrollSucceeded) { |
| 396 | + dst.file.set("FTE", true); | ||
| 421 | dst.m() = Mat(); | 397 | dst.m() = Mat(); |
| 422 | } | 398 | } |
| 423 | } catch (std::exception &e) { | 399 | } catch (std::exception &e) { |
| @@ -426,7 +402,7 @@ struct CT8Enroll : public UntrainableTransform | @@ -426,7 +402,7 @@ struct CT8Enroll : public UntrainableTransform | ||
| 426 | } | 402 | } |
| 427 | }; | 403 | }; |
| 428 | 404 | ||
| 429 | -BR_REGISTER(Transform, CT8Enroll) | 405 | +BR_REGISTER(Transform, CT8EnrollTransform) |
| 430 | 406 | ||
| 431 | /*! | 407 | /*! |
| 432 | * \ingroup distances | 408 | * \ingroup distances |