Skip to content

Commit

Permalink
Merge pull request #269 from nicholasc/facemark
Browse files Browse the repository at this point in the history
Facemark API
  • Loading branch information
justadudewhohacks authored Apr 25, 2018
2 parents 3608d5a + d7f4444 commit 1cc4ac8
Show file tree
Hide file tree
Showing 26 changed files with 1,206 additions and 40 deletions.
6 changes: 6 additions & 0 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@
"cc/modules/face/EigenFaceRecognizer.cc",
"cc/modules/face/FisherFaceRecognizer.cc",
"cc/modules/face/LBPHFaceRecognizer.cc",
"cc/modules/face/Facemark.cc",
"cc/modules/face/FacemarkAAM.cc",
"cc/modules/face/FacemarkAAMData.cc",
"cc/modules/face/FacemarkAAMParams.cc",
"cc/modules/face/FacemarkLBF.cc",
"cc/modules/face/FacemarkLBFParams.cc",
"cc/modules/text/text.cc",
"cc/modules/text/OCRHMMClassifier.cc",
"cc/modules/text/OCRHMMDecoder.cc",
Expand Down
28 changes: 27 additions & 1 deletion cc/macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@
#define FF_GETTER(clazz, name, prop) \
NAN_GETTER(name) { info.GetReturnValue().Set(Nan::ObjectWrap::Unwrap<clazz>(info.This())->prop); }

#define FF_GETTER_SIMPLE(clazz, name, prop, converter) \
NAN_GETTER(name) { \
v8::Local<v8::Value> jsValue = converter::wrap( \
Nan::ObjectWrap::Unwrap<clazz>(info.This())->prop \
); \
info.GetReturnValue().Set(jsValue); \
}

#define FF_GETTER_COMPLEX(clazz, name, prop, converter) FF_GETTER_SIMPLE(clazz, name, prop, converter)

#define FF_GETTER_JSOBJ(clazz, name, value, unwrapper, ctor) \
NAN_GETTER(name) { \
v8::Local<v8::Object> jsObj = FF_NEW_INSTANCE(ctor); \
Expand Down Expand Up @@ -96,4 +106,20 @@ static FF_FUNC_TYPE ff_func = FF_FUNC_TYPE();
#define FF_SETTER_NUMBER(clazz, name, prop) FF_SETTER(clazz, name, prop, ff_number)
#define FF_SETTER_BOOL(clazz, name, prop) FF_SETTER(clazz, name, prop, ff_bool)

#endif
#define FF_SETTER_SIMPLE(clazz, name, prop, converter) \
NAN_SETTER(name##Set) { \
FF_METHOD_CONTEXT(#name); \
Nan::ObjectWrap::Unwrap<clazz>(info.This())->prop = converter::unwrap( \
value \
); \
}

#define FF_SETTER_COMPLEX(clazz, name, prop, type, converter) \
NAN_SETTER(name##Set) { \
FF_METHOD_CONTEXT(#name); \
type target; \
converter::unwrap(&target, value); \
Nan::ObjectWrap::Unwrap<clazz>(info.This())->prop = target; \
}

#endif
174 changes: 174 additions & 0 deletions cc/modules/face/Facemark.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
#ifdef HAVE_FACE

#include "Facemark.h"
#include "FacemarkBindings.h"

#if CV_VERSION_MINOR >= 4

NAN_METHOD(Facemark::Save) {
FF_METHOD_CONTEXT("Facemark::Save");
FF_ARG_STRING(0, std::string path);
FF_UNWRAP(info.This(), Facemark)->save(path);
}

NAN_METHOD(Facemark::Load) {
FF_METHOD_CONTEXT("Facemark::Load");
FF_ARG_STRING(0, std::string path);
FF_UNWRAP(info.This(), Facemark)->load(path);
}

void Facemark::Init(v8::Local<v8::FunctionTemplate> ctor) {
Nan::SetPrototypeMethod(ctor, "addTrainingSample", AddTrainingSample);
Nan::SetPrototypeMethod(ctor, "addTrainingSampleAsync",
AddTrainingSampleAsync);
Nan::SetPrototypeMethod(ctor, "loadModel", LoadModel);
Nan::SetPrototypeMethod(ctor, "loadModelAsync", LoadModelAsync);
Nan::SetPrototypeMethod(ctor, "getData", GetData);
Nan::SetPrototypeMethod(ctor, "getDataAsync", GetDataAsync);
Nan::SetPrototypeMethod(ctor, "getFaces", GetFaces);
Nan::SetPrototypeMethod(ctor, "getFacesAsync", GetFacesAsync);
Nan::SetPrototypeMethod(ctor, "setFaceDetector", SetFaceDetector);
Nan::SetPrototypeMethod(ctor, "training", Training);
Nan::SetPrototypeMethod(ctor, "trainingAsync", TrainingAsync);
Nan::SetPrototypeMethod(ctor, "fit", Fit);
Nan::SetPrototypeMethod(ctor, "fitAsync", FitAsync);
Nan::SetPrototypeMethod(ctor, "save", Save);
Nan::SetPrototypeMethod(ctor, "load", Load);
};

NAN_METHOD(Facemark::AddTrainingSample) {
FF::SyncBinding(
std::make_shared<FacemarkBindings::AddTrainingSampleWorker>(FF_UNWRAP(info.This(), Facemark)->getFacemark()),
"Facemark::AddTrainingSample",
info
);
}

NAN_METHOD(Facemark::AddTrainingSampleAsync) {
FF::AsyncBinding(
std::make_shared<FacemarkBindings::AddTrainingSampleWorker>(FF_UNWRAP(info.This(), Facemark)->getFacemark()),
"Facemark::AddTrainingSampleAsync",
info
);
}

NAN_METHOD(Facemark::LoadModel) {
FF::SyncBinding(
std::make_shared<FacemarkBindings::LoadModelWorker>(FF_UNWRAP(info.This(), Facemark)->getFacemark()),
"Facemark::LoadModel",
info
);
}

NAN_METHOD(Facemark::LoadModelAsync) {
FF::AsyncBinding(
std::make_shared<FacemarkBindings::LoadModelWorker>(FF_UNWRAP(info.This(), Facemark)->getFacemark()),
"Facemark::LoadModelAsync",
info
);
}

NAN_METHOD(Facemark::GetData) {
FF::SyncBinding(
std::make_shared<FacemarkBindings::GetDataWorker>(FF_UNWRAP(info.This(), Facemark)->getFacemark()),
"Facemark::GetData",
info
);
}

NAN_METHOD(Facemark::GetDataAsync) {
FF::AsyncBinding(
std::make_shared<FacemarkBindings::GetDataWorker>(FF_UNWRAP(info.This(), Facemark)->getFacemark()),
"Facemark::GetDataAsync",
info
);
}

NAN_METHOD(Facemark::GetFaces) {
FF::SyncBinding(
std::make_shared<FacemarkBindings::GetFacesWorker>(FF_UNWRAP(info.This(), Facemark)->getFacemark()),
"Facemark::GetFaces",
info
);
}

NAN_METHOD(Facemark::GetFacesAsync) {
FF::AsyncBinding(
std::make_shared<FacemarkBindings::GetFacesWorker>(FF_UNWRAP(info.This(), Facemark)->getFacemark()),
"Facemark::GetFacesAsync",
info
);
}

NAN_METHOD(Facemark::SetFaceDetector) {
FF_METHOD_CONTEXT("SetFaceDetector");

if (!info[0]->IsFunction()) {
return Nan::ThrowError(Nan::New("Facemark::SetFaceDetector - Error: "
"expected argument 0 to be of type")
.ToLocalChecked());
}

FF_ARG_FUNC(0, v8::Local<v8::Function> cbFunc);
Nan::Callback *callback = new Nan::Callback(cbFunc);

bool results = FF_UNWRAP(info.This(), Facemark)
->getFacemark()
->setFaceDetector((cv::face::FN_FaceDetector)detector, callback);

info.GetReturnValue().Set(Nan::New<v8::Boolean>(results));
}

NAN_METHOD(Facemark::Training) {
FF::SyncBinding(
std::make_shared<FacemarkBindings::TrainingWorker>(FF_UNWRAP(info.This(), Facemark)->getFacemark()),
"Facemark::Train",
info
);
}

NAN_METHOD(Facemark::TrainingAsync) {
FF::AsyncBinding(
std::make_shared<FacemarkBindings::TrainingWorker>(FF_UNWRAP(info.This(), Facemark)->getFacemark()),
"Facemark::TrainAsync",
info
);
}

NAN_METHOD(Facemark::Fit) {
FF::SyncBinding(
std::make_shared<FacemarkBindings::FitWorker>(FF_UNWRAP(info.This(), Facemark)->getFacemark()),
"Facemark::Fit",
info
);
}

NAN_METHOD(Facemark::FitAsync) {
FF::AsyncBinding(
std::make_shared<FacemarkBindings::FitWorker>(FF_UNWRAP(info.This(), Facemark)->getFacemark()),
"Facemark::FitAsync",
info
);
}

bool Facemark::detector(cv::InputArray image, cv::OutputArray faces,
Nan::Callback *callback) {
Nan::HandleScope scope;

cv::Mat frame = image.getMat().clone();
v8::Local<v8::Value> jsMat = Mat::Converter::wrap(frame);

v8::Local<v8::Value> argv[] = {jsMat};
FF_OBJ jsObject = callback->Call(1, argv)->ToObject();

std::vector<cv::Rect> _faces;
ObjectArrayConverter<Rect, cv::Rect>::unwrap(&_faces, jsObject);

cv::Mat(_faces).copyTo(faces);

return true;
}

#endif

#endif
44 changes: 44 additions & 0 deletions cc/modules/face/Facemark.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "NativeNodeUtils.h"
#include "Mat.h"
#include "Point.h"
#include "Rect.h"
#include "macros.h"
#include <iostream>
#include <opencv2/face.hpp>

#if CV_VERSION_MINOR >= 4

#ifndef __FF_FACEMARK_H__
#define __FF_FACEMARK_H__

class Facemark : public Nan::ObjectWrap {
public:
virtual cv::Ptr<cv::face::Facemark> getFacemark() = 0;
virtual void save(std::string) = 0;
virtual void load(std::string) = 0;

static void Init(v8::Local<v8::FunctionTemplate>);

static NAN_METHOD(AddTrainingSample);
static NAN_METHOD(AddTrainingSampleAsync);
static NAN_METHOD(LoadModel);
static NAN_METHOD(LoadModelAsync);
static NAN_METHOD(GetData);
static NAN_METHOD(GetDataAsync);
static NAN_METHOD(GetFaces);
static NAN_METHOD(GetFacesAsync);
static NAN_METHOD(SetFaceDetector);
static NAN_METHOD(Training);
static NAN_METHOD(TrainingAsync);
static NAN_METHOD(Fit);
static NAN_METHOD(FitAsync);
static NAN_METHOD(Save);
static NAN_METHOD(Load);

static bool detector(cv::InputArray image, cv::OutputArray faces,
Nan::Callback *callback);
};

#endif

#endif
43 changes: 43 additions & 0 deletions cc/modules/face/FacemarkAAM.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifdef HAVE_FACE

#include "FacemarkAAM.h"
#include "FacemarkAAMParams.h"

#if CV_VERSION_MINOR >= 4

Nan::Persistent<v8::FunctionTemplate> FacemarkAAM::constructor;

NAN_MODULE_INIT(FacemarkAAM::Init) {
v8::Local<v8::FunctionTemplate> ctor =
Nan::New<v8::FunctionTemplate>(FacemarkAAM::New);
v8::Local<v8::ObjectTemplate> instanceTemplate = ctor->InstanceTemplate();

Facemark::Init(ctor);
constructor.Reset(ctor);
ctor->SetClassName(Nan::New("FacemarkAAM").ToLocalChecked());
instanceTemplate->SetInternalFieldCount(1);

target->Set(Nan::New("FacemarkAAM").ToLocalChecked(), ctor->GetFunction());
};

NAN_METHOD(FacemarkAAM::New) {
FF_METHOD_CONTEXT("FacemarkAAM::New");

FF_ARG_INSTANCE_IFDEF(
0,
cv::face::FacemarkAAM::Params params,
FacemarkAAMParams::constructor,
FF_UNWRAP_FACEMARKAAMPARAMS_AND_GET,
cv::face::FacemarkAAM::Params()
);

FacemarkAAM *self = new FacemarkAAM();
self->Wrap(info.Holder());
self->facemark = cv::face::FacemarkAAM::create(params);

FF_RETURN(info.Holder());
};

#endif

#endif
27 changes: 27 additions & 0 deletions cc/modules/face/FacemarkAAM.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "Facemark.h"

#if CV_VERSION_MINOR >= 4

#ifndef __FF_FACEMARKAAM_H__
#define __FF_FACEMARKAAM_H__

class FacemarkAAM : public Facemark {
public:
cv::Ptr<cv::face::Facemark> facemark;

void save(std::string path) { facemark->save(path); }

void load(std::string path) {
cv::Algorithm::load<cv::face::FacemarkAAM>(path);
}

static NAN_MODULE_INIT(Init);
static NAN_METHOD(New);

static Nan::Persistent<v8::FunctionTemplate> constructor;
cv::Ptr<cv::face::Facemark> getFacemark() { return facemark; }
};

#endif

#endif
33 changes: 33 additions & 0 deletions cc/modules/face/FacemarkAAMData.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifdef HAVE_FACE

#include "FacemarkAAMData.h"

#if CV_VERSION_MINOR >= 4

Nan::Persistent<v8::FunctionTemplate> FacemarkAAMData::constructor;

NAN_MODULE_INIT(FacemarkAAMData::Init) {
v8::Local<v8::FunctionTemplate> ctor =
Nan::New<v8::FunctionTemplate>(FacemarkAAMData::New);
v8::Local<v8::ObjectTemplate> instanceTemplate = ctor->InstanceTemplate();

constructor.Reset(ctor);
ctor->SetClassName(FF_NEW_STRING("FacemarkAAMData"));
instanceTemplate->SetInternalFieldCount(1);

Nan::SetAccessor(instanceTemplate, FF_NEW_STRING("s0"), s0Get, s0Set);

target->Set(FF_NEW_STRING("FacemarkAAMData"), ctor->GetFunction());
};

NAN_METHOD(FacemarkAAMData::New) {
FF_METHOD_CONTEXT("FacemarkAAMData::New");
FacemarkAAMData *self = new FacemarkAAMData();
self->data = cv::face::FacemarkAAM::Data();
self->Wrap(info.Holder());
FF_RETURN(info.Holder());
};

#endif

#endif
Loading

0 comments on commit 1cc4ac8

Please sign in to comment.