虹软人脸识别ArcSoft3.0NodeJs 版本实现
ArcSoft3.0_Nodejs
一、项目说明
虹软官网传送门 ,有不同平台和不同版本的sdk,有需要的根据业务下载。
此次项目支持windows和linux系统,mac 由于 禁用electron打包的应用。
- 项目由electron-vue脚手架创建。
- 在主线程中实现与虹软SDK交互,如果还需要和render层交互,还需使用app.on来接收render层传过来的业务。
- vue打包时,需要在package.json中配置包含路径。
- 采用ffi库调用C++库,ref资料1
ref资料2
ref资料3
其它的请自行百度,此处就不细细阐述了。 - 图片处理有两种,一种是opencv4nodejs(node版本大于10.x,我用的是10的最后一版本,最新版本的用的python3.3,编译问题太多),一种是jimp,都有方法实现,我推荐opencv,处理速度快,但是配置环境略复杂。
资料看官方的npm即可,其余资料参考python调用opencv的方法类似。 - 此次主要针对window版本的dll,linux调用方法一样,将路径换位自己的路径即可,文件名为.so
二、ffi安装及环境安装
1、安装 Visual Studio 15 生成工具 2017
利用 微软自带的安装exe 【vs_BuildTools.exe】
目录:C:\Users\Administrator\.windows-build-tools,脚本安装时,会因为安装包过大和网络问题,导致安装失败。2、指定编译MSBuild.exe位置,因为2019和上述装的2017都有这个exe,最好使用2017的,2019我安装失败了。
npm config set msbuild_path "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe"3、指定python版本,还是建议2.7,其他高版本问题太多,我的3.8.5(不推荐)
npm config set python C:/Python27
npm config set python C:/python3.8.53、安装gyp
npm install node-gyp -g
或者
npm install --global node-gyp@latest4、安装ffi ref
npm install ffi -g
npm install ref -g
成功编译
三、opencv4nodejs的安装
手动安装opencv的环境,设置环境变量
OPENCV_BIN_DIR=E:\commonsoft\opencv\build\x64\vc14\bin
OPENCV_INCLUDE_DIR=E:\commonsoft\opencv\build\include
OPENCV_LIB_DIR=E:\commonsoft\opencv\build\x64\vc14\lib此处这么安装,成功率90%
set OPENCV4NODEJS_DISABLE_AUTOBUILD=1
npm i -g opencv4nodejs
四、代码结构
├─.electron-vue
├─.idea
├─build
│ └─icons
├─dist
│ ├─electron
│ └─web
├─images
├─src
│ ├─main
│ │ ├─inc
│ │ ├─lib
│ │ │ ├─X64
│ │ │ └─X86
│ │ └─modual
│ │ ├─img
│ │ │ ├─faces
│ │ │ └─test
│ │ └─log
│ └─renderer
│ ├─assets
│ ├─components
│ │ └─LandingPage
│ ├─router
│ └─store
│ └─modules
├─static
└─test├─e2e│ └─specs└─unitmodual文件夹为人脸识别工作目录
lib文件夹为放置dll文件路径的地方,x86 x64 为对应的版本
img 图片路径(faces 为 drawFace 的操作路径 test 是 cvImages 的操作路径)
五、代码调用实例及说明
const arc_face = require('./face_engine');
const path = require('path');
const config = require('./config');
const m = require('./logger');
const client = require('./clients');
const imageHelper = require('./face_cv_image');
const fsUtil = require('./fileUtils');// 设置dll路径
let dllPath = "";
if (process.env.NODE_ENV !== 'development') {dllPath = require('path').join(__dirname, '../../main/lib/X64').replace(/\\/g, '\\\\')
}else{dllPath = require('path').join(__dirname, '../lib/X64').replace(/\\/g, '\\\\')
}
// 添加DLL所在目录到环境变量
process.env['PATH'] = `${process.env.PATH};${dllPath}`;// 初始化接口
const arc = new arc_face(config.lib_win64);Object.prototype.toString = function(){return JSON.stringify(this);
};Date.prototype.toLocaleString = function() {return this.getFullYear() + "-" + (this.getMonth() + 1) + "-" + this.getDate() + " " + this.getHours() + ":" + this.getMinutes() + ":" + this.getSeconds();
};this.test_arc = async () => {try{let dataInfo = arc.getActiveFileInfo();if (null != dataInfo){let start = new Date(parseInt(dataInfo.startTime) * 1000);let end = new Date(parseInt(dataInfo.endTime) * 1000);m.logger.info("expire date is from %s to %s, please check the date for expired.thank you.",start.toLocaleString(),end.toLocaleString());if (new Date().getTime() > end){m.logger.warn('your arc soft is expired,please change the file to continue use it,thank you.');return;}}client.get('active', (err, res) => {// 激活if (!res || parseInt(res) !== 1){let ib = arc.activeFaceEngine(config.appId,config.appKey);client.set('active',ib?1:0);}else{m.logger.info("engine has already initialed, do not repeat active");}});let version = arc.getVersion();m.logger.info("current verson is %s",version.Version);// 初始化引擎arc.initialFaceEngine(16,50);// 设置可信度arc.setLiveParam(0.5,0.7);let img_path1 = path.join(__dirname, './img/1.jpg');let img_path2 = path.join(__dirname, './img/2.jpg');let img_path3 = path.join(__dirname, './img/3.jpg');// jimp 处理图片// let asvl1 = await imageHelper.parseImage(img_path1,false);// let asvl2 = await imageHelper.parseImage(img_path2,false);// let asvl3 = await imageHelper.parseImage(img_path3,false);// opencv 处理图片let asvl1 = await imageHelper.cvImages(img_path1,false,path.join(__dirname, './img/test'));let asvl2 = await imageHelper.cvImages(img_path2,false,path.join(__dirname, './img/test'));let asvl3 = await imageHelper.cvImages(img_path3,false,path.join(__dirname, './img/test'));// 检测人脸let data1 = arc.detectFacesEx(asvl1.imageData);let data2 = arc.detectFacesEx(asvl2.imageData);// 提取特征值let feature1 = arc.extractFeature(asvl1.imageData, data1.multi.faceRect[0], data1.multi.faceOrient[0]);let feature2 = arc.extractFeature(asvl2.imageData, data2.multi.faceRect[0], data2.multi.faceOrient[0]);if (!feature1 || !feature2){m.logger.error("feature1 or feature2 is null. please check.");return;}// console.log("feature1",feature1)// console.log("feature2",feature2)// 比较let sim = arc.compareFeature(feature1.nav,feature2.nav);if (sim < 0){m.logger.info("similar is %d,is not the same person.",sim);return;}if (sim > 0.8){m.logger.info("similar is %d,is the same person.",sim);}else{m.logger.info("similar is %d,is not the same person.",sim);}// base64 转 feature 测试 ,实际效果会差0.02let f1 = arc.base64ToFeature(feature1.nab.featureBuffer);let f2 = arc.base64ToFeature(feature2.nab.featureBuffer);let ff = arc.compareFeature(f1,f2);if (ff > 0.8){m.logger.info("similar is %d,is the same person.",ff);}else{m.logger.info("similar is %d,is not the same person.",ff);}// 释放人脸指针arc.release(f1.feature);arc.release(f2.feature);// 单体检测let ib = arc.processEx(asvl3.imageData,false);if (!ib){m.logger.error("single process checked failed.");return;}arc.getSexInfo();arc.getAgeInfo();arc.getAngleInfo();arc.getLivenessScore(false);// 测试画框let isIR = false;let asvl5 = await imageHelper.cvImages(img_path1,isIR);let infos = arc.detectFacesEx(asvl5.imageData);let filePath = path.join(__dirname, './img/faces');await fsUtil.dirExists(filePath);imageHelper.drawFace(img_path1,infos.multi,true,filePath);// detect 和 process 系列let fileCv = path.join(__dirname, './img/test');await fsUtil.dirExists(fileCv);let asvl6 = await imageHelper.cvImages(img_path1,isIR,fileCv);let faces = arc.detectFaces(asvl6,false);let info = arc.processNone(asvl6,false);arc.getLivenessScore(false);// console.log('info',info);// 释放 函数中已经释放调用的指针arc.unInitialEngine();client.quit();}catch (e) {m.logger.info("some error happened.%s",e.toString());arc.unInitialEngine();client.quit()}
};this.test_arc();
六、安装及使用
# install dependencies
npm install# serve with hot reload at localhost:9080
npm run dev# build electron application for production
npm run build# run unit & end-to-end tests
npm test# 测试人脸部分
node face_test.js
七、常见问题
1、Dynamic Linking Error: Win32 error 126
这个错误有三种原因(1)通常是传入的 DLL 路径错误,找不到 Dll 文件,推荐使用绝对路径。
(2)如果是在 x64 的node/electron下引用 32 位的 DLL,也会报这个错,反之亦然。要确保 DLL 要求的 CPU 架构和你的运行环境相同。
DLL 还有引用其他 DLL 文件,但是找不到引用的 DLL 文件,可能是 VC 依赖库或者多个 DLL 之间存在依赖关系。
设置dll的工作的环境变量
process.env['PATH'] = `${process.env.PATH};${'E:/arface_node/arface_nodejs/src/main/lib/X64'}` //添加DLL所在目录到环境变量
Dynamic Linking Error: Win32 error 127:DLL
(3)没有找到对应名称的函数,需要检查头文件定义的函数名是否与 DLL 调用时写的函数名是否相同。2、electron-vue 运行问题,如果提示app of undefined 类似的问题,在创建窗体时加入如下模块
enableRemoteModule:true, // 加入此句就可以获取app模块,就不会报错了3、在node里面,指针 -> 缓存(buffer),
如 let a = new (typedef.MInt32.size) 表示 a*,
a.deref() 可以取出指针中的值,
普通变量 b, 那 b.ref() 表示 b*
.size 相当于C++ 里面的 size_t4、调用C++ 第一步就是对应 数据类型// ref提供了C++的基本数据类型和定义,nodejs参数类型和C语言参数类型转换
const ref = require('ref');
typedef.MLong = ref.types.long;
typedef.UMLong = ref.types.uint32;
typedef.MFloat = ref.types.float;// 提供 C++ 结构体定义方法
const StructType = require('ref-struct');
typedef.__tag_rect = StructType({left: typedef.MInt32,top: typedef.MInt32,right: typedef.MInt32,bottom: typedef.MInt32
});
// 提供 C++ 数组定义方法
const ArrayType = require('ref-array');
ppu8Plane: ArrayType(ref.refType(typedef.MUInt8), 4),
ref.refType(XXX)表示指针5、C++接口映射
// 一种是不带回调函数的,如下:
ffi.Library(libFile, {// 映射的接口名称 C++接口,对应的数据类型ASFGetActiveFileInfo: [TypeDef.MRESULT,[TypeDef.LPASF_ActiveFileInfo // [out] 激活文件信息]]
}// 一种是带回调函数的调用
let libname = ffi.Library('./libname', {'setCallback': ['void', ['pointer']]
});let callback = ffi.Callback('void', ['int', 'string'],function(id, name) {console.log("id: ", id);console.log("name: ", name);
});libname.setCallback(callback);
// 退出时引用回调指针以避免GC(垃圾回收)
process.on('exit', function() {callback
});6、指针拷贝操作,用到 linux 中的 libc 操作
分配指定大小的空间指针: libc.malloc(size);
初始化指针:libc.memset(*p,offset,size);
指针拷贝:libc.memcpy(*to, *from ,size);7、结合node中的buffer,将指针拷贝至buffer
const arr = new Buffer(TypeDef.MByte.size);
for (let i = 0; i < _feature.featureSize; i++) {libc.memcpy(arr.address(), feature.feature.address() + i * TypeDef.MByte.size, TypeDef.MByte.size);this.pointers.push(feature.feature);_normal.feature.push(ref.get(arr, 0, TypeDef.MByte));
}
arr.deref()即取出指针中的值8、分配的指针空间一定要释放
libc.free(*p)
了解更多人脸识别产品相关内容请到虹软视觉开放平台哦
虹软人脸识别ArcSoft3.0NodeJs 版本实现相关推荐
- 初次使用虹软人脸识别SDK C++版本
本文章是基于虹软人脸识别SDK3.0,VS2019 首先,下载虹软人脸识别SDK,按照此目录下的PDF文件完成工程配置. 配置完成后,需要在以下目录将从官网获取的APPID以及SDKKEY进行填写,然 ...
- java用虹软人脸识别SDK实现人脸识别,运行ArcSoft的Java版本Demo出错,未检出人脸
java.lang.UnsatisfiedLinkError: Can't load library: d:\face_libs\libarcsoft_ java用虹软人脸识别SDK实现人脸识别 网上 ...
- java用虹软人脸识别SDK实现人脸识别,运行ArcSoft的Java版本Demo出错,未检出人脸(已解决)
java用虹软人脸识别SDK实现人脸识别,运行ArcSoft的Java版本Demo出错,未检出人脸问题已解决!!! 原因: 虹软人脸识别SDK版本问题! 下载的java版本的demo的SDK是arcs ...
- 虹软人脸识别WPF版本,含活体检测
虹软人脸识别WPF版本,3.0类库,含活体检测 源码地址: https://gitee.com/dacaba/arcface-demo-csharp-wpf3 将对应appid和appkey替换App ...
- 虹软java接摄像头_虹软人脸识别SDK(java+linux/window) 初试
虹软人脸识别全平台demo调用-快速上手之服务端Windows篇 demo名称:ArcFace 2.2 Windows(86) Demo [C++] 一 环境配置: 1) 安装VS2013环境安装包( ...
- 虹软人脸识别SDK接入Milvus实现海量人脸快速检索
虹软人脸识别SDK接入Milvus实现海量人脸快速检索 背景 虹软SDK及Milvus简介 开发环境 虹软人脸识别SDK使用简介 Milvus环境搭建 快速检索实现 人脸识别流程简介 快速检索 虹软S ...
- 基于RTSP视频流的Java后台服务端虹软人脸识别
1 概述 人脸识别技术是随着技术发展而产生的生物识别技术,目前已广泛应用于安防领域,主要用于身份验证和身份识别.视频监控是安防系统常见的一种表现形式,需要部署各种摄像头,包括网络摄像头IP ...
- 虹软人脸识别 - 人脸特征数据的存取
虹软人脸识别 - 人脸特征数据的存取 文章目录 虹软人脸识别 - 人脸特征数据的存取 一.简介 二.数据库应用 1. 连接数据库 2. 建表 3. 注册人脸并保存其特征值到数据库 4. 获取人脸特征数 ...
- Android 虹软人脸识别获取数据的方法
前言 最近app要上一个新的功能 在客户点击购买的时候 记录客户的基本信息 比如年龄和性别 为后期做大数据分析做铺垫 在网上找第三方 找到了虹软人脸识别 在这里吐槽一下 免费的虹软 真是很坑 客服没人 ...
最新文章
- 中科院遗传发育所王秀杰团队鉴定出10种潜在的2019-nCoV蛋白酶抑制剂
- android Java BASE64编码和解码一:基础
- 特征因子是什么意思_生态因子作用的一般特征
- 创建型模式 简单工厂模式
- nginx+memcached+captcha_server实现验证码服务器
- 随想录(用python开发网站)
- 修改成绩用c语言怎么编程,用C语言编程平均分数
- 摘抄和总结--确保搞砸人工智能项目的十种方法
- Springboot实现filter拦截token验证和跨域
- win10 更新 英特尔显示器音频 后显示器音箱没有声音
- 最全整理浏览器兼容性问题与解决方案
- 量子计算机原理 不确定,【图片】不确定性原理对量子纠缠的解释【经典物理吧】_百度贴吧...
- 程序员这高薪岗位只有计算机专业的能做?
- prometheus入门实例
- https://www.cloudmidi.net/ableton-live-11-suite-v11-0-macos.html
- Java8 Stream API 详细使用指南
- VMware -- 克隆虚拟机
- Python 计算思维训练——输入和错误处理练习(二)第三关
- CP-VTON学习笔记
- 考研党看这里,福昕阅读器领鲜版让你如虎添翼
热门文章
- 大学学了一年Python之后开始兼职,平均每个月赚3030块
- 怎么在多个快递单号中快速找出没有物流的单号
- jupyter 快捷键
- 关于Rstudio最新版本中Biobase和GEOquery安装的问题
- tomcat基本介绍
- js判断时间是否为当天(今天是今天)
- python延时执行函数_一日一技:在 Python 中实现延迟调用
- mmcv/_ext.cpython-36m-x86_64-linux-gnu.so: undefined symbol: _ZN6caffe28Type
- WIN7 bootmgr is conmpressed 无法开机
- http升级为https全过程(通过nginx安装SSL证书)