Skip to content
This repository was archived by the owner on Oct 18, 2023. It is now read-only.

Commit 4ecb4e8

Browse files
committed
Facemark API implementation
1 parent 932f0fe commit 4ecb4e8

22 files changed

+1054
-38
lines changed

binding.gyp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@
6565
"cc/modules/face/EigenFaceRecognizer.cc",
6666
"cc/modules/face/FisherFaceRecognizer.cc",
6767
"cc/modules/face/LBPHFaceRecognizer.cc",
68+
"cc/modules/face/Facemark.cc",
69+
"cc/modules/face/FacemarkAAM.cc",
70+
"cc/modules/face/FacemarkAAMParams.cc",
71+
"cc/modules/face/FacemarkLBF.cc",
72+
"cc/modules/face/FacemarkLBFParams.cc",
6873
"cc/modules/text/text.cc",
6974
"cc/modules/text/OCRHMMClassifier.cc",
7075
"cc/modules/text/OCRHMMDecoder.cc",

cc/modules/face/Facemark.cc

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
#ifdef HAVE_FACE
2+
3+
#include "Facemark.h"
4+
#include "FacemarkAAMData.h"
5+
6+
void Facemark::Init(v8::Local<v8::FunctionTemplate> ctor) {
7+
Nan::SetPrototypeMethod(ctor, "addTrainingSample", AddTrainingSample);
8+
Nan::SetPrototypeMethod(ctor, "addTrainingSampleAsync",
9+
AddTrainingSampleAsync);
10+
Nan::SetPrototypeMethod(ctor, "loadModel", LoadModel);
11+
Nan::SetPrototypeMethod(ctor, "loadModelAsync", LoadModelAsync);
12+
Nan::SetPrototypeMethod(ctor, "getData", GetData);
13+
Nan::SetPrototypeMethod(ctor, "getDataAsync", GetDataAsync);
14+
Nan::SetPrototypeMethod(ctor, "getFaces", GetFaces);
15+
Nan::SetPrototypeMethod(ctor, "getFacesAsync", GetFacesAsync);
16+
Nan::SetPrototypeMethod(ctor, "setFaceDetector", SetFaceDetector);
17+
Nan::SetPrototypeMethod(ctor, "training", Training);
18+
Nan::SetPrototypeMethod(ctor, "trainingAsync", TrainingAsync);
19+
Nan::SetPrototypeMethod(ctor, "fit", Fit);
20+
Nan::SetPrototypeMethod(ctor, "fitAsync", FitAsync);
21+
Nan::SetPrototypeMethod(ctor, "save", Save);
22+
Nan::SetPrototypeMethod(ctor, "load", Load);
23+
};
24+
25+
struct Facemark::AddTrainingSampleWorker : public SimpleWorker {
26+
public:
27+
cv::Ptr<cv::face::Facemark> self;
28+
AddTrainingSampleWorker(cv::Ptr<cv::face::Facemark> self) {
29+
this->self = self;
30+
}
31+
32+
bool results;
33+
cv::Mat image;
34+
std::vector<cv::Point2f> landmarks;
35+
36+
const char *execute() {
37+
results = self->addTrainingSample(image, landmarks);
38+
return "";
39+
}
40+
41+
v8::Local<v8::Value> getReturnValue() {
42+
v8::Local<v8::Value> ret = Nan::New<v8::Boolean>(results);
43+
return ret;
44+
}
45+
46+
bool unwrapRequiredArgs(Nan::NAN_METHOD_ARGS_TYPE info) {
47+
return (Mat::Converter::arg(0, &image, info) ||
48+
ObjectArrayConverter<Point2, cv::Point2d, cv::Point2f>::arg(
49+
1, &landmarks, info));
50+
}
51+
};
52+
53+
NAN_METHOD(Facemark::AddTrainingSample) {
54+
AddTrainingSampleWorker worker(
55+
FF_UNWRAP(info.This(), Facemark)->getFacemark());
56+
FF_WORKER_SYNC("Facemark::AddTrainingSample", worker);
57+
info.GetReturnValue().Set(worker.getReturnValue());
58+
}
59+
60+
NAN_METHOD(Facemark::AddTrainingSampleAsync) {
61+
AddTrainingSampleWorker worker(
62+
FF_UNWRAP(info.This(), Facemark)->getFacemark());
63+
FF_WORKER_ASYNC("Facemark::AddTrainingSampleAsync", AddTrainingSampleWorker,
64+
worker);
65+
}
66+
67+
struct Facemark::LoadModelWorker : public SimpleWorker {
68+
public:
69+
cv::Ptr<cv::face::Facemark> self;
70+
LoadModelWorker(cv::Ptr<cv::face::Facemark> self) { this->self = self; }
71+
72+
std::string model;
73+
74+
const char *execute() {
75+
self->loadModel(model);
76+
return "";
77+
}
78+
79+
bool unwrapRequiredArgs(Nan::NAN_METHOD_ARGS_TYPE info) {
80+
return (StringConverter::arg(0, &model, info));
81+
}
82+
};
83+
84+
NAN_METHOD(Facemark::LoadModel) {
85+
LoadModelWorker worker(FF_UNWRAP(info.This(), Facemark)->getFacemark());
86+
FF_WORKER_SYNC("Facemark::LoadModel", worker);
87+
info.GetReturnValue().Set(worker.getReturnValue());
88+
}
89+
90+
NAN_METHOD(Facemark::LoadModelAsync) {
91+
LoadModelWorker worker(FF_UNWRAP(info.This(), Facemark)->getFacemark());
92+
FF_WORKER_ASYNC("Facemark::LoadModelAsync", LoadModelWorker, worker);
93+
}
94+
95+
struct Facemark::GetDataWorker : public SimpleWorker {
96+
public:
97+
cv::Ptr<cv::face::Facemark> self;
98+
GetDataWorker(cv::Ptr<cv::face::Facemark> self) { this->self = self; }
99+
100+
cv::face::FacemarkAAM::Data data;
101+
102+
const char *execute() {
103+
self->getData(&data);
104+
return "";
105+
}
106+
107+
v8::Local<v8::Value> getReturnValue() {
108+
v8::Local<v8::Value> ret = InstanceConverter<FacemarkAAMData, cv::face::FacemarkAAM::Data>::wrap(data);
109+
return ret;
110+
}
111+
};
112+
113+
NAN_METHOD(Facemark::GetData) {
114+
GetDataWorker worker(FF_UNWRAP(info.This(), Facemark)->getFacemark());
115+
FF_WORKER_SYNC("Facemark::GetData", worker);
116+
info.GetReturnValue().Set(worker.getReturnValue());
117+
}
118+
119+
NAN_METHOD(Facemark::GetDataAsync) {
120+
GetDataWorker worker(FF_UNWRAP(info.This(), Facemark)->getFacemark());
121+
FF_WORKER_ASYNC("Facemark::GetDataAsync", GetDataWorker, worker);
122+
}
123+
124+
struct Facemark::GetFacesWorker : public SimpleWorker {
125+
public:
126+
cv::Ptr<cv::face::Facemark> self;
127+
GetFacesWorker(cv::Ptr<cv::face::Facemark> self) { this->self = self; }
128+
129+
cv::Mat image;
130+
std::vector<cv::Rect> faces;
131+
132+
const char *execute() {
133+
self->getFaces(image, faces);
134+
return "";
135+
}
136+
137+
v8::Local<v8::Value> getReturnValue() {
138+
v8::Local<v8::Value> ret =
139+
ObjectArrayConverter<Rect, cv::Rect>::wrap(faces);
140+
return ret;
141+
}
142+
143+
bool unwrapRequiredArgs(Nan::NAN_METHOD_ARGS_TYPE info) {
144+
return (Mat::Converter::arg(0, &image, info));
145+
}
146+
};
147+
148+
NAN_METHOD(Facemark::GetFaces) {
149+
GetFacesWorker worker(FF_UNWRAP(info.This(), Facemark)->getFacemark());
150+
FF_WORKER_SYNC("Facemark::GetFaces", worker);
151+
info.GetReturnValue().Set(worker.getReturnValue());
152+
}
153+
154+
NAN_METHOD(Facemark::GetFacesAsync) {
155+
GetFacesWorker worker(FF_UNWRAP(info.This(), Facemark)->getFacemark());
156+
FF_WORKER_ASYNC("Facemark::GetFacesAsync", GetFacesWorker, worker);
157+
}
158+
159+
bool Facemark::detector(cv::InputArray image, cv::OutputArray faces,
160+
Nan::Callback *callback) {
161+
Nan::HandleScope scope;
162+
163+
cv::Mat frame = image.getMat().clone();
164+
v8::Local<v8::Value> jsMat = Mat::Converter::wrap(frame);
165+
166+
v8::Local<v8::Value> argv[] = {jsMat};
167+
FF_OBJ jsObject = callback->Call(1, argv)->ToObject();
168+
169+
std::vector<cv::Rect> _faces;
170+
ObjectArrayConverter<Rect, cv::Rect>::unwrap(&_faces, jsObject);
171+
172+
cv::Mat(_faces).copyTo(faces);
173+
174+
return true;
175+
}
176+
177+
NAN_METHOD(Facemark::SetFaceDetector) {
178+
FF_METHOD_CONTEXT("SetFaceDetector");
179+
180+
if (!info[0]->IsFunction()) {
181+
return Nan::ThrowError(Nan::New("Facemark::SetFaceDetector - Error: "
182+
"expected argument 0 to be of type")
183+
.ToLocalChecked());
184+
}
185+
186+
FF_ARG_FUNC(0, v8::Local<v8::Function> cbFunc);
187+
188+
Nan::Callback *callback = new Nan::Callback(cbFunc);
189+
190+
bool results = FF_UNWRAP(info.This(), Facemark)
191+
->getFacemark()
192+
->setFaceDetector((cv::face::FN_FaceDetector)detector, callback);
193+
194+
info.GetReturnValue().Set(Nan::New<v8::Boolean>(results));
195+
}
196+
197+
struct Facemark::TrainingWorker : public SimpleWorker {
198+
public:
199+
cv::Ptr<cv::face::Facemark> self;
200+
TrainingWorker(cv::Ptr<cv::face::Facemark> self) { this->self = self; }
201+
202+
const char *execute() {
203+
self->training();
204+
return "";
205+
}
206+
};
207+
208+
NAN_METHOD(Facemark::Training) {
209+
TrainingWorker worker(FF_UNWRAP(info.This(), Facemark)->getFacemark());
210+
FF_WORKER_SYNC("Facemark::Train", worker);
211+
info.GetReturnValue().Set(worker.getReturnValue());
212+
}
213+
214+
NAN_METHOD(Facemark::TrainingAsync) {
215+
TrainingWorker worker(FF_UNWRAP(info.This(), Facemark)->getFacemark());
216+
FF_WORKER_ASYNC("Facemark::TrainAsync", TrainingWorker, worker);
217+
}
218+
219+
struct Facemark::FitWorker : public SimpleWorker {
220+
public:
221+
cv::Ptr<cv::face::Facemark> self;
222+
FitWorker(cv::Ptr<cv::face::Facemark> self) { this->self = self; }
223+
224+
cv::Mat image;
225+
std::vector<cv::Rect> faces;
226+
std::vector<std::vector<cv::Point2f>> landmarks;
227+
228+
const char *execute() {
229+
self->fit(image, faces, landmarks);
230+
return "";
231+
}
232+
233+
v8::Local<v8::Value> getReturnValue() {
234+
v8::Local<v8::Value> ret =
235+
ObjectArrayOfArraysConverter<Point2, cv::Point2d, cv::Point2f>::wrap(
236+
landmarks);
237+
return ret;
238+
}
239+
240+
bool unwrapRequiredArgs(Nan::NAN_METHOD_ARGS_TYPE info) {
241+
return (Mat::Converter::arg(0, &image, info) ||
242+
ObjectArrayConverter<Rect, cv::Rect>::arg(1, &faces, info));
243+
}
244+
};
245+
246+
NAN_METHOD(Facemark::Fit) {
247+
FitWorker worker(FF_UNWRAP(info.This(), Facemark)->getFacemark());
248+
FF_WORKER_SYNC("Facemark::Fit", worker);
249+
info.GetReturnValue().Set(worker.getReturnValue());
250+
}
251+
252+
NAN_METHOD(Facemark::FitAsync) {
253+
FitWorker worker(FF_UNWRAP(info.This(), Facemark)->getFacemark());
254+
FF_WORKER_ASYNC("Facemark::FitAsync", FitWorker, worker);
255+
}
256+
257+
NAN_METHOD(Facemark::Save) {
258+
FF_METHOD_CONTEXT("Facemark::Save");
259+
FF_ARG_STRING(0, std::string path);
260+
FF_UNWRAP(info.This(), Facemark)->save(path);
261+
}
262+
263+
NAN_METHOD(Facemark::Load) {
264+
FF_METHOD_CONTEXT("Facemark::Load");
265+
FF_ARG_STRING(0, std::string path);
266+
FF_UNWRAP(info.This(), Facemark)->load(path);
267+
}
268+
269+
#endif

cc/modules/face/Facemark.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include "Converters.h"
2+
#include "Mat.h"
3+
#include "Point.h"
4+
#include "Rect.h"
5+
#include "Workers.h"
6+
#include "macros.h"
7+
#include <iostream>
8+
#include <opencv2/face.hpp>
9+
10+
#ifndef __FF_FACEMARK_H__
11+
#define __FF_FACEMARK_H__
12+
13+
class Facemark : public Nan::ObjectWrap {
14+
public:
15+
virtual cv::Ptr<cv::face::Facemark> getFacemark() = 0;
16+
virtual void save(std::string) = 0;
17+
virtual void load(std::string) = 0;
18+
19+
static void Init(v8::Local<v8::FunctionTemplate>);
20+
21+
struct AddTrainingSampleWorker;
22+
static NAN_METHOD(AddTrainingSample);
23+
static NAN_METHOD(AddTrainingSampleAsync);
24+
25+
struct LoadModelWorker;
26+
static NAN_METHOD(LoadModel);
27+
static NAN_METHOD(LoadModelAsync);
28+
29+
struct GetDataWorker;
30+
static NAN_METHOD(GetData);
31+
static NAN_METHOD(GetDataAsync);
32+
33+
struct GetFacesWorker;
34+
static NAN_METHOD(GetFaces);
35+
static NAN_METHOD(GetFacesAsync);
36+
37+
static bool detector(cv::InputArray image, cv::OutputArray faces,
38+
Nan::Callback *callback);
39+
40+
struct SetFaceDetectorWorker;
41+
static NAN_METHOD(SetFaceDetector);
42+
43+
struct TrainingWorker;
44+
static NAN_METHOD(Training);
45+
static NAN_METHOD(TrainingAsync);
46+
47+
struct FitWorker;
48+
static NAN_METHOD(Fit);
49+
static NAN_METHOD(FitAsync);
50+
51+
static NAN_METHOD(Save);
52+
static NAN_METHOD(Load);
53+
};
54+
55+
#endif

cc/modules/face/FacemarkAAM.cc

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#ifdef HAVE_FACE
2+
3+
#include "FacemarkAAM.h"
4+
#include "FacemarkAAMParams.h"
5+
6+
Nan::Persistent<v8::FunctionTemplate> FacemarkAAM::constructor;
7+
8+
NAN_MODULE_INIT(FacemarkAAM::Init) {
9+
v8::Local<v8::FunctionTemplate> ctor =
10+
Nan::New<v8::FunctionTemplate>(FacemarkAAM::New);
11+
v8::Local<v8::ObjectTemplate> instanceTemplate = ctor->InstanceTemplate();
12+
13+
Facemark::Init(ctor);
14+
constructor.Reset(ctor);
15+
ctor->SetClassName(Nan::New("FacemarkAAM").ToLocalChecked());
16+
instanceTemplate->SetInternalFieldCount(1);
17+
18+
target->Set(Nan::New("FacemarkAAM").ToLocalChecked(), ctor->GetFunction());
19+
};
20+
21+
NAN_METHOD(FacemarkAAM::New) {
22+
FF_METHOD_CONTEXT("FacemarkAAM::New");
23+
24+
FF_ARG_INSTANCE_IFDEF(
25+
0,
26+
cv::face::FacemarkAAM::Params params,
27+
FacemarkAAMParams::constructor,
28+
FF_UNWRAP_FACEMARKAAMPARAMS_AND_GET,
29+
cv::face::FacemarkAAM::Params()
30+
);
31+
32+
FacemarkAAM *self = new FacemarkAAM();
33+
self->Wrap(info.Holder());
34+
self->facemark = cv::face::FacemarkAAM::create(params);
35+
36+
FF_RETURN(info.Holder());
37+
};
38+
39+
#endif

0 commit comments

Comments
 (0)