hzt_asc 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CMakeLists.txt CHANGED
@@ -28,6 +28,7 @@ target_link_libraries(${PROJECT_NAME} arcsoft_face)
28
28
  target_link_libraries(${PROJECT_NAME} arcsoft_face_engine)
29
29
 
30
30
  target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})
31
+ target_link_libraries(${PROJECT_NAME} curl)
31
32
 
32
33
  set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
33
34
  # Include Node-API wrappers
package/ask.cc CHANGED
@@ -2,6 +2,8 @@
2
2
  #include <opencv2/opencv.hpp>
3
3
  #include <opencv2/highgui/highgui.hpp>
4
4
  #include <opencv2/imgproc/imgproc.hpp>
5
+ #include <curl/curl.h>
6
+
5
7
  #include <vector>
6
8
  #include <fstream>
7
9
  #include <iostream>
@@ -22,6 +24,10 @@ using namespace cv;
22
24
  #define SafeDelete(p) { if ((p)) delete (p); (p) = NULL; }
23
25
  #define NSCALE 16
24
26
  #define FACENUM 5
27
+
28
+
29
+
30
+
25
31
  Napi::Value errorData(Napi::Env env, string msg) {
26
32
  Napi::Object obj = Napi::Object::New(env);
27
33
  obj.Set(Napi::String::New(env, "errorMsg"), msg);
@@ -38,7 +44,11 @@ Napi::Object ASK::Init(Napi::Env env, Napi::Object exports) {
38
44
  InstanceMethod("FaceFeatureInfo", &ASK::faceFeatureInfo),
39
45
  //InstanceMethod("RegisterFaceFeature", &ASK::RegisterFaceFeature),
40
46
  //InstanceMethod("SearchFaceFeature", &ASK::SearchFaceFeature),
41
- InstanceMethod("ImageFaceCompare", &ASK::ImageFaceCompare)});
47
+ InstanceMethod("ImageFaceCompare", &ASK::ImageFaceCompare),
48
+ InstanceMethod("FaceDetectUrl", &ASK::faceDetectUrl),
49
+ InstanceMethod("FaceFeatureExtractUrl", &ASK::faceFeatureExtractUrl),
50
+ InstanceMethod("ImageFaceCompareUrl", &ASK::ImageFaceCompareUrl)
51
+ });
42
52
  exports.Set("ASK", func);
43
53
  return exports;
44
54
  }
@@ -68,7 +78,7 @@ ASK::ASK(const Napi::CallbackInfo& info) : Napi::ObjectWrap<ASK>(info) {
68
78
  }
69
79
  //初始化引擎
70
80
  MHandle handle = NULL;
71
- MInt32 mask = ASF_FACE_DETECT | ASF_FACERECOGNITION | ASF_FACE3DANGLE ; // ASF_AGE | ASF_GENDER | | ASF_LIVENESS
81
+ MInt32 mask = ASF_FACE_DETECT | ASF_FACERECOGNITION | ASF_FACE3DANGLE | ASF_AGE | ASF_GENDER | ASF_LIVENESS; //
72
82
  res = ASFInitEngine(ASF_DETECT_MODE_IMAGE, ASF_OP_0_ONLY, NSCALE, FACENUM, mask, &handle);
73
83
  if (res != MOK) {
74
84
  printf("ASFInitEngine fail: %d\n", res);
@@ -130,6 +140,40 @@ Napi::Value ASK::faceDetect(const Napi::CallbackInfo& info) {
130
140
  }
131
141
 
132
142
 
143
+ Napi::Value ASK::faceDetectUrl(const Napi::CallbackInfo& info) {
144
+ Napi::Env env = info.Env();
145
+ int length = info.Length();
146
+ if (length != 1 || !info[0].IsString() ) {
147
+ Napi::TypeError::New(env, "input expected").ThrowAsJavaScriptException();
148
+ return errorData(env, "input expected"); //Napi::Number::New(info.Env(), -1);
149
+ }
150
+ string filePath = info[0].As<Napi::String>().ToString();
151
+ ASVLOFFSCREEN offscreen = { 0 };
152
+ MUInt8* imageData;
153
+ processFileUrl(filePath.c_str(), imageData, offscreen);
154
+ ASF_MultiFaceInfo detectedFaces = { 0 };
155
+ MRESULT res = ASFDetectFacesEx(this->handle, &offscreen, &detectedFaces);
156
+ //cout << "faceNum:" << detectedFaces.faceNum << endl;
157
+
158
+ Napi::Object obj = Napi::Object::New(env);
159
+ obj.Set(Napi::String::New(env, "faceNum"), detectedFaces.faceNum);
160
+ Napi::Array list = Napi::Array::New(env, detectedFaces.faceNum);
161
+ for(int i = 0; i < detectedFaces.faceNum; ++i) {
162
+ ASF_SingleFaceInfo sData;
163
+ getDetectFaceInfo(detectedFaces, sData, i);
164
+ Napi::Object data = Napi::Object::New(env);
165
+ data.Set(Napi::String::New(env, "left"), sData.faceRect.left);
166
+ data.Set(Napi::String::New(env, "top"), sData.faceRect.top);
167
+ data.Set(Napi::String::New(env, "right"), sData.faceRect.right);
168
+ data.Set(Napi::String::New(env, "bottom"), sData.faceRect.bottom);
169
+ list[i] = data;
170
+ }
171
+ obj.Set(Napi::String::New(env, "faceRects"), list);
172
+ SafeArrayDelete(imageData);
173
+ return obj;
174
+ }
175
+
176
+
133
177
 
134
178
  Napi::Value ASK::faceFeatureExtract(const Napi::CallbackInfo& info) {
135
179
  Napi::Env env = info.Env();
@@ -172,6 +216,46 @@ Napi::Value ASK::faceFeatureExtract(const Napi::CallbackInfo& info) {
172
216
  return obj;
173
217
  }
174
218
 
219
+ Napi::Value ASK::faceFeatureExtractUrl(const Napi::CallbackInfo& info) {
220
+ Napi::Env env = info.Env();
221
+ int length = info.Length();
222
+ if (length != 1 || !info[0].IsString() ) {
223
+ Napi::TypeError::New(env, "input expected").ThrowAsJavaScriptException();
224
+ return errorData(env, "input expected"); //Napi::Number::New(info.Env(), -1);
225
+ }
226
+ string filePath = info[0].As<Napi::String>().ToString();
227
+
228
+ ASVLOFFSCREEN offscreen = { 0 };
229
+ MUInt8* imageData;
230
+ processFileUrl(filePath.c_str(), imageData, offscreen);
231
+ ASF_MultiFaceInfo detectedFaces = { 0 };
232
+ MRESULT res = ASFDetectFacesEx(this->handle, &offscreen, &detectedFaces);
233
+
234
+ Napi::Object obj = Napi::Object::New(env);
235
+ obj.Set(Napi::String::New(env, "faceNum"), detectedFaces.faceNum);
236
+ if (0 == detectedFaces.faceNum) {
237
+ return obj;
238
+ }
239
+ Napi::Array list = Napi::Array::New(env, detectedFaces.faceNum);
240
+ for(int i = 0; i < detectedFaces.faceNum; ++i) {
241
+ ASF_SingleFaceInfo sData;
242
+ getDetectFaceInfo(detectedFaces, sData, i);
243
+ ASF_FaceFeature feature = { 0 };
244
+ res = ASFFaceFeatureExtractEx(this->handle, &offscreen, &sData, &feature);
245
+ Napi::Object data = Napi::Object::New(env);
246
+ data.Set(Napi::String::New(env, "left"), sData.faceRect.left);
247
+ data.Set(Napi::String::New(env, "top"), sData.faceRect.top);
248
+ data.Set(Napi::String::New(env, "right"), sData.faceRect.right);
249
+ data.Set(Napi::String::New(env, "bottom"), sData.faceRect.bottom);
250
+ data.Set(Napi::String::New(env, "featureSize"), feature.featureSize);
251
+ data.Set(Napi::String::New(env, "feature"), Napi::ArrayBuffer::New(env, feature.feature, feature.featureSize));
252
+ list[i] = data;
253
+
254
+ }
255
+ obj.Set(Napi::String::New(env, "faceRects"), list);
256
+ SafeArrayDelete(imageData);
257
+ return obj;
258
+ }
175
259
 
176
260
 
177
261
  Napi::Value ASK::faceFeatureInfo(const Napi::CallbackInfo& info) {
@@ -356,6 +440,90 @@ Napi::Value ASK::ImageFaceCompare(const Napi::CallbackInfo& info) {
356
440
  return obj;
357
441
  }
358
442
 
443
+ Napi::Value ASK::ImageFaceCompareUrl(const Napi::CallbackInfo& info) {
444
+ Napi::Env env = info.Env();
445
+ int length = info.Length();
446
+ if (length < 3) {
447
+ Napi::TypeError::New(env, "input expected").ThrowAsJavaScriptException();
448
+ return errorData(env, "input expected");
449
+ }
450
+ string filePath = info[0].As<Napi::String>().ToString();
451
+ ASVLOFFSCREEN offscreen = { 0 };
452
+ MUInt8* imageData;
453
+ processFileUrl(filePath.c_str(), imageData, offscreen);
454
+ ASF_MultiFaceInfo detectedFaces = { 0 };
455
+ MRESULT res = ASFDetectFacesEx(this->handle, &offscreen, &detectedFaces);
456
+ Napi::Object obj = Napi::Object::New(env);
457
+ obj.Set(Napi::String::New(env, "faceNum"), detectedFaces.faceNum);
458
+ if (0 == detectedFaces.faceNum) {
459
+ return obj;
460
+ }
461
+
462
+ //输入参数
463
+ if (!info[1].IsArray()) {
464
+ Napi::TypeError::New(env, "array expected").ThrowAsJavaScriptException();
465
+ return errorData(env, "array expected");
466
+ }
467
+ Napi::Array arr = info[1].As<Napi::Array>();
468
+ MUInt32 len = arr.Length();
469
+ ASF_FaceFeatureInfo* featureInfoList = new ASF_FaceFeatureInfo[len];
470
+ for(int i = 0; i < len; ++i) {
471
+ Napi::Object obj = static_cast<Napi::Value>(arr[i]).As<Napi::Object>().ToObject();
472
+ MInt32 searchId = obj.Get(static_cast<napi_value>(Napi::String::New(info.Env(),"searchId"))).As<Napi::Number>().Uint32Value();
473
+ std::string* tag = new std::string();
474
+ *tag = obj.Get(static_cast<napi_value>(Napi::String::New(info.Env(),"tag"))).As<Napi::String>().ToString();
475
+ Napi::ArrayBuffer buf = obj.Get(static_cast<napi_value>(Napi::String::New(info.Env(),"feature"))).As<Napi::ArrayBuffer>();
476
+ ASF_FaceFeature* featureInfo = new ASF_FaceFeature();
477
+ featureInfo->featureSize = buf.ByteLength();
478
+ featureInfo->feature = reinterpret_cast<MByte*>(buf.Data());;
479
+ ASF_FaceFeatureInfo* info = new ASF_FaceFeatureInfo();
480
+ info->searchId = searchId;
481
+ info->tag = (*tag).c_str();
482
+ info->feature = featureInfo;
483
+ featureInfoList[i] = *info;
484
+ }
485
+
486
+ //compare
487
+ Napi::Array list = Napi::Array::New(env, detectedFaces.faceNum);
488
+ for(int i = 0; i < detectedFaces.faceNum; ++i) {
489
+ ASF_SingleFaceInfo sData;
490
+ getDetectFaceInfo(detectedFaces, sData, i);
491
+ ASF_FaceFeature feature = { 0 };
492
+ res = ASFFaceFeatureExtractEx(handle, &offscreen, &sData, &feature);
493
+ MFaceSore* faceScores = new MFaceSore[len];
494
+ for(int j = 0; j < len; ++j) {
495
+ MFloat confidenceLevel;
496
+ MRESULT res1 = ASFFaceFeatureCompare(this->handle, &feature, featureInfoList[j].feature, &confidenceLevel);
497
+ MFaceSore* pFace = new MFaceSore();
498
+ pFace->searchId = featureInfoList[j].searchId;
499
+ pFace->score = confidenceLevel;
500
+ pFace->name = featureInfoList[j].tag;
501
+ faceScores[j] = *pFace;
502
+ }
503
+ sort(faceScores, faceScores + len, compareScore);
504
+ int ll = len > 5? 5 : len;
505
+ Napi::Array mFaceScores = Napi::Array::New(env, ll);
506
+ for(int n = 0; n < ll; ++n) {
507
+ Napi::Object faceScore = Napi::Object::New(env);
508
+ faceScore.Set(Napi::String::New(env, "searchId"), faceScores[n].searchId);
509
+ faceScore.Set(Napi::String::New(env, "score"), faceScores[n].score);
510
+ faceScore.Set(Napi::String::New(env, "name"), faceScores[n].name);
511
+ mFaceScores[n] = faceScore;
512
+ }
513
+ Napi::Object data = Napi::Object::New(env);
514
+ data.Set(Napi::String::New(env, "left"), sData.faceRect.left);
515
+ data.Set(Napi::String::New(env, "top"), sData.faceRect.top);
516
+ data.Set(Napi::String::New(env, "right"), sData.faceRect.right);
517
+ data.Set(Napi::String::New(env, "bottom"), sData.faceRect.bottom);
518
+ data.Set(Napi::String::New(env, "faceScores"), mFaceScores);
519
+ list[i] = data;
520
+ delete []faceScores;
521
+ }
522
+ obj.Set(Napi::String::New(env, "faceRects"), list);
523
+ SafeArrayDelete(imageData);
524
+ delete []featureInfoList;
525
+ return obj;
526
+ }
359
527
 
360
528
 
361
529
  ////获取激活信息(采集离线激活信息、激活文件信息、SDK版本信息)
@@ -445,6 +613,7 @@ void ASK::processFile(const char* filePath, MUInt8* imageData, ASVLOFFSCREEN& o
445
613
  cv::Mat src = imread(filePath);
446
614
  int Width = src.cols;
447
615
  int Height = src.rows;
616
+ cout << "Width:" << Width << ",Height:"<<Height<<endl;
448
617
  int wScore = Width % 4;
449
618
  int hScore = Height % 2;
450
619
  if (wScore != 0 || hScore != 0) {
@@ -465,6 +634,83 @@ void ASK::processFile(const char* filePath, MUInt8* imageData, ASVLOFFSCREEN& o
465
634
  dest.release();
466
635
  ColorSpaceConversion(Width, Height, ASVL_PAF_NV21, imageData, offscreen);
467
636
  }
637
+ //curl writefunction to be passed as a parameter
638
+ // we can't ever expect to get the whole image in one piece,
639
+ // every router / hub is entitled to fragment it into parts
640
+ // (like 1-8k at a time),
641
+ // so insert the part at the end of our stream.
642
+ size_t write_data(char *ptr, size_t size, size_t nmemb, void *userdata)
643
+ {
644
+ vector<uchar> *stream = (vector<uchar>*)userdata;
645
+ //cout<<ptr<< size<<endl;
646
+ size_t count = size * nmemb;
647
+ stream->insert(stream->end(), ptr, ptr + count);
648
+ //cout<<count<<endl;
649
+ return count;
650
+ }
651
+
652
+ //function to retrieve the image as cv::Mat data type
653
+ cv::Mat curlImg(const char *img_url, int timeout=100000)
654
+ {
655
+ cout<<img_url<<endl;
656
+ vector<uchar> stream;
657
+ CURL *curl = curl_easy_init();
658
+ curl_easy_setopt(curl, CURLOPT_URL, img_url); //the img url
659
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); // pass the writefunction
660
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &stream); // pass the stream ptr to the writefunction
661
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); // timeout if curl_easy hangs,
662
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); //重定向一次
663
+ CURLcode res = curl_easy_perform(curl); // start curl
664
+ curl_easy_cleanup(curl); // cleanup
665
+ cout<<res<<"xxxx" << stream.size() << " " << stream.max_size()<<endl;
666
+ return imdecode(stream, -1); // 'keep-as-is'
667
+ }
668
+ void ASK::processFileUrl(const char* url, MUInt8* imageData, ASVLOFFSCREEN& offscreen) {
669
+ cv::Mat src = curlImg(url);
670
+ int Width = src.cols;
671
+ int Height = src.rows;
672
+ cout << "Width:" << Width << ",Height:"<<Height<<endl;
673
+ int wScore = Width % 4;
674
+ int hScore = Height % 2;
675
+ if (wScore != 0 || hScore != 0) {
676
+ Width -= wScore;
677
+ Height -= hScore;
678
+ cv::Mat dst;
679
+ cv::resize(src, dst, cv::Size(Width, Height));
680
+ src.release();
681
+ src = dst;
682
+ }
683
+ cv::Mat dest;
684
+ cvtColor(src, dest, COLOR_BGR2YUV_I420);
685
+ int len = Height*Width*3/2;
686
+ imageData = (MUInt8*)malloc(len);
687
+ memset(imageData, 0, len);
688
+ memcpy(imageData, dest.data, len);
689
+ src.release();
690
+ dest.release();
691
+ ColorSpaceConversion(Width, Height, ASVL_PAF_NV21, imageData, offscreen);
692
+ }
693
+
694
+
695
+
696
+
697
+
698
+
699
+
700
+
701
+
702
+
703
+
704
+
705
+
706
+
707
+
708
+
709
+
710
+
711
+
712
+
713
+
468
714
 
469
715
 
470
716
  // Napi::Value ASK::RegisterFaceFeature(const Napi::CallbackInfo& info) {
package/ask.h CHANGED
@@ -25,11 +25,16 @@ class ASK : public Napi::ObjectWrap<ASK> {
25
25
 
26
26
  Napi::Value ImageFaceCompare(const Napi::CallbackInfo& info);
27
27
 
28
+ Napi::Value faceDetectUrl(const Napi::CallbackInfo& info);
29
+ Napi::Value faceFeatureExtractUrl(const Napi::CallbackInfo& info);
30
+ Napi::Value ImageFaceCompareUrl(const Napi::CallbackInfo& info);
31
+
28
32
  private:
29
33
  void getSdkRelatedInfo();
30
34
  void timestampToTime(char* timeStamp, char* dateTime, int dateTimeSize);
31
35
  int ColorSpaceConversion(MInt32 width, MInt32 height, MInt32 format, MUInt8* imgData, ASVLOFFSCREEN& offscreen);
32
36
  void processFile(const char* filePath, MUInt8* imageData, ASVLOFFSCREEN& offscreen);
37
+ void processFileUrl(const char* filePath, MUInt8* imageData, ASVLOFFSCREEN& offscreen);
33
38
 
34
39
  // void mFaceDetect(ASVLOFFSCREEN& offscree, ASF_MultiFaceInfo* detectedFaces);
35
40
  // void mFaceFeatureExtract(ASVLOFFSCREEN& offscree, ASF_MultiFaceInfo* detectedFaces);
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "hzt_asc",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "main": "index.js",
5
5
  "description": "hzt_asc_v3.",
6
6
  "author": {
7
- "name": "wucpeng",
8
- "email": "wuchangpeng@haizitong.com"
7
+ "name": "wuyunpeng",
8
+ "email": "wuyunpeng37@163.com"
9
9
  },
10
10
  "dependencies": {
11
11
  "bindings": "~1.2.1",
package/sample/demo.js CHANGED
@@ -19,40 +19,45 @@ printMem()
19
19
  console.log("init end", Date.now() - start);
20
20
 
21
21
  for(let i = 0; i < 1; ++i) {
22
- let num = ask.FaceDetect(path.join(__dirname, '../images/20200829105722.jpg'))
22
+ let num = ask.FaceDetect("/home/haizitong/workspace/hztFace/700dceca74304e11b6a48806df9085d2.png")
23
23
  console.log("FaceDetect", num)
24
24
  printMem()
25
+
26
+ let det = ask.FaceDetectUrl("http://min.haizitong.com/2/ali/i/700dceca74304e11b6a48806df9085d2");
27
+ console.log("det", det);
25
28
  }
26
29
 
27
30
  // console.log(num)
28
31
  console.log("detect end", Date.now() - start);
29
32
  let feature = null;
30
33
  for(let i = 0; i < 1; ++i) {
31
- let num2 = ask.FaceFeatureExtract(path.join(__dirname, '../images/20200829105722.jpg'))
34
+ let num2 = ask.FaceFeatureExtract("/home/haizitong/workspace/hztFace/24aea309c9fa4d809b3b8f88782936a5.png")
32
35
  console.log("FaceFeatureExtract", num2);
33
36
  if (num2.faceNum && num2.faceRects.length) {
34
37
  feature = num2.faceRects[0].feature;
35
38
  }
39
+ let num22 = ask.FaceFeatureExtractUrl("http://min.haizitong.com/2/ali/i/24aea309c9fa4d809b3b8f88782936a5")
40
+ console.log("FaceFeatureExtract2", num22);
36
41
  printMem()
37
42
  }
38
- console.log("extract end", Date.now() - start);
43
+ // console.log("extract end", Date.now() - start);
39
44
 
40
- //FaceFeatureCompare
41
- if (feature) {
42
- let compareResult = ask.FaceFeatureCompare(feature, feature);
43
- console.log("FaceFeatureCompare", compareResult);
44
- console.log("FaceFeatureCompare end", Date.now() - start);
45
- let list = [
46
- {searchId: 1, tag: "wo", feature},
47
- {searchId: 2, tag: "wo2", feature},
48
- ];
49
- let imageResult = ask.ImageFaceCompare(path.join(__dirname, '../images/20200829105722.jpg'), list, 1);
50
- console.log("imageResult", JSON.stringify(imageResult, null, 4));
51
- console.log("ImageFaceCompare end", Date.now() - start);
52
- let str = Buffer.from(feature).toString('base64');
53
- console.log("str", str, str.length);
45
+ // //FaceFeatureCompare
46
+ // if (feature) {
47
+ // let compareResult = ask.FaceFeatureCompare(feature, feature);
48
+ // console.log("FaceFeatureCompare", compareResult);
49
+ // console.log("FaceFeatureCompare end", Date.now() - start);
50
+ // let list = [
51
+ // {searchId: 1, tag: "wo", feature},
52
+ // {searchId: 2, tag: "wo2", feature},
53
+ // ];
54
+ // let imageResult = ask.ImageFaceCompare(path.join(__dirname, '../images/20200829105722.jpg'), list, 1);
55
+ // console.log("imageResult", JSON.stringify(imageResult, null, 4));
56
+ // console.log("ImageFaceCompare end", Date.now() - start);
57
+ // let str = Buffer.from(feature).toString('base64');
58
+ // console.log("str", str, str.length);
54
59
 
55
- }
60
+ // }
56
61
 
57
62
 
58
63
  // let num5 = ask.FaceFeatureInfo(path.join(__dirname, '../images/20200829105722.jpg'))