ArcSoft3.0_Nodejs1.项目说明虹软官网门户,有不同平台和不同版本的SDK,如有需要请根据业务下载。本项目支持windows和linux系统,mac禁用electron打包的应用。该项目是使用electron-vue脚手架创建的。在主线程中实现与虹软SDK的交互。如果需要与渲染层进行交互,则需要使用app.on来接收来自渲染层的业务。vue打包时需要在package.json中配置include路径。使用ffi库调用C++库,refdata1refdata2refdata3其他请自行百度,这里不再赘述。图像处理有两种,一种是opencv4nodejs(node版本大于10.x,我用的是10的最新版本,最新版本用的是python3.3,编译问题太多),另一种是jimp,都是方法实现,推荐opencv,处理速度快,但配置环境略复杂。有关信息,请参阅官方npm。其他参考python调用opencv的方法。这次主要是针对window版本的dll。linux的调用方法也是一样的,只是把路径换成自己的路径即可,文件名为.so。安装exe[vs_BuildTools.exe]目录:C:\Users\Administrator\.windows-build-tools,脚本安装时会因为安装包过大和网络问题导致安装失败。2.指定编译MSBuild.exe的位置,因为2019和上面说的2017都有这个exe,最好用2017,2019我安装失败。npmconfigsetmsbuild_path"C:\ProgramFiles(x86)\MicrosoftVisualStudio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe"3.指定python版本,或者推荐2.7。其他高版本问题太多。3.8.5(不推荐)npmconfigsetpythonC:/Python27npmconfigsetpythonC:/python3.8.53,installgypnpminstallnode-gyp-gornpminstall--globalnode-gyp@latest4,installffirefnpminstallffi-gnpminstallref-g编译成功3.opencv4nodejs安装手动安装opencv环境,设置环境变量OPENCV_BIN_DIR=E:\commonsoft\opencv\build\x64\vc14\binOPENCV_INCLUDE_DIR=E:\commonsoft\opencv\build\includeOPENCV_LIB_DIR=E:\commonsoft\opencv\build\x64\vc14\lib这里这样安装,成功率90%setOPENCV4NODEJS_DISABLE_AUTOBUILD=1npmi-gopencv4nodejs4.代码结构├─.electron-vue├─.idea├─build│-模态││├─img││├─faces││└─test││└─log│└─renderer│├─assets│├─components││└─LandingPage│├─router││└─modules├─static└─test├─e2e│└─specs└─unitmodal文件夹为人脸识别工作目录lib文件夹为放置dll文件路径,x86x64为对应版本img图片路径(faces为drawFace的操作路径测试为cvImages的操作路径)5.代码调用示例及说明constarc_face=require('./face_engine');constpath=require('路径');constconfig=require('./config');constm=require('./logger');constclient=require('./clients');constimageHelper=require('./face_cv_image');constfsUtil=require('./fileUtils');//设置dll路径letdllPath="";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}`;//初始化接口constarc=newarc_face(config.lib_win64);Object.prototype.toString=function(){returnJSON.stringify(this);};Date.prototype.toLocaleString=function(){returnthis.getFullYear()+"-"+(this.getMonth()+1)+"-"+this.getDate()+""+this.getHours()+":"+this.getMinutes()+":"+this.getSeconds();};this.test_arc=async()=>{try{letdataInfo=arc.getActiveFileInfo();if(null!=dataInfo){letstart=newDate(parseInt(dataInfo.startTime)*1000);letend=newDate(parseInt(dataInfo.endTime)*1000);m.logger.info("过期日期是从%s到%s,请检查过期日期。谢谢。",start.toLocaleString(),end.toLocaleString());if(newDate().getTime()>end){m.logger.warn('您的arcsoft已过期,请更改文件继续使用,谢谢。');返回;}}client.get('active',(err,res)=>{//激活if(!res||parseInt(res)!==1){letib=arc.activeFaceEngine(config.appId,config.应用密钥);client.set('active',ib?1:0);}else{m.logger.info("engine已经初始化,不再重复激活");}});让版本=arc.getVersion();m.logger.info("当前版本是%s",version.Version);//初始化引擎arc.initialFaceEngine(16,50);//设置可信度arc.setLiveParam(0.5,0.7);让img_path1=path.join(__dirname,'./img/1.jpg');让img_path2=path.join(__dirname,'./img/2.jpg');让img_path3=path.join(__dirname,'./img/3.jpg');//jimp处理图片//letasvl1=awaitimageHelper.parseImage(img_path1,false);//letasvl2=awaitimageHelper.parseImage(img_path2,false);//letasvl3=awaitimageHelper.parseImage(img_path3,false);//opencv处理图片letasvl1=awaitimageHelper.cvImages(img_path1,false,path.join(__dirname,'./img/test'));letasvl2=awaitimageHelper.cvImages(img_path2,false,path.join(__dirname,'./img/test'));letasvl3=awaitimageHelper.cvImages(img_path3,false,path.join(__dirname,'./img/test'));//检测人脸letdata1=arc.detectFacesEx(asvl1.imageData);让data2=arc.detectFacesEx(asvl2.imageData);//提取特征值letfeature1=arc.extractFeature(asvl1.imageData,data1.multi.faceRect[0],data1.multi.faceOrient[0]);让feature2=arc.extractFeature(asvl2.imageData,data2.multi.faceRect[0],data2.multi.faceOrient[0]);if(!feature1||!feature2){m.logger.error("feature1或feature2为空。请检查。");返回;}//console.log("feature1",feature1)//console.log("feature2",feature2)//比较letsim=arc.compareFeature(feature1.nav,feature2.nav);if(sim<0){m.logger.info("相似的是%d,不是同一个人。",sim);返回;}if(sim>0.8){米。logger.info("相似的是%d,是同一个人。",sim);}else{m.logger.info("相似的是%d,不是同一个人。",sim);}//base64切换到特征测试,实际效果会相差0.02letf1=arc.base64ToFeature(feature1.nab.featureBuffer);让f2=arc.base64ToFeature(feature2.nab.featureBuffer);让ff=arc.compareFeature(f1,f2);if(ff>0.8){m.logger.info("相似的是%d,是同一个人。",ff);}else{m.logger.info("相似的是%d,不是同一个人。",ff);}//释放面指针arc.release(f1.feature);arc.release(f2.feature);//单次检测letib=arc.processEx(asvl3.imageData,false);if(!ib){m.logger.error("单个进程检查失败。");返回;}arc.getSexInfo();arc.getAgeInfo();arc.getAngleInfo();arc.getLivenessScore(假);//测试框架letisIR=false;letasvl5=awaitimageHelper.cvImages(img_path1,isIR);让infos=arc.detectFacesEx(asvl5.imageData);让filePath=path.join(__dirname,'./img/faces');等待fsUtil.dirExists(文件路径);imageHelper.drawFace(img_path1,infos.multi,true,filePath);//检测并处理序列letfileCv=path.join(__dirname,'./img/test');等待fsUtil.dirExists(fileCv);letasvl6=awaitimageHelper.cvImages(img_path1,isIR,fileCv);让faces=arc.detectFaces(asvl6,false);让info=arc.processNone(asvl6,false);arc.getLivenessScore(假);//console.log('信息',信息);//释放释放函数中已经调用的指针arc.unInitialEngine();客户退出();}catch(e){m.logger.info("发生错误。%s",e.toString());arc.unInitialEngine();client.quit()}};this.test_arc();六、安装和使用#installdependenciesnpminstall#servewithhotreloadatlocalhost:9080npmrundev#buildelectronapplicationforproductionnpmrunbuild#rununit&end-to-endtestsnpmtest#testthefacepartnodeface_test.js七、常见问题1、DynamicLinkingError:Win32error126三种原因这个错误(1)一般是传入的DLL路径错误,找不到Dll文件。建议使用绝对路径。(2)如果在x64node/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从目录到环境变量DynamicLinkingError:Win32error127:DLL(3)找不到对应名称的函数。需要检查头文件中定义的函数名是否与调用DLL时写入的函数名相同。2、electron-vue运行问题,如果提示appofundefined类似问题,在创建表单时添加如下模块enableRemoteModule:true//添加这句获取app模块,不会报错3.在node中,指针->缓存(buffer),比如leta=new(typedef.MInt32.size)表示a*,a.deref()可以取出指针中的值,普通变量b,然后b.ref()表示b*.size等同于C++中的size_t4。调用C++第一步是对应数据类型//ref提供了C++的基本数据类型和定义,nodejs参数类型和C语言参数类型转换constref=require('ref');typedef.MLong=ref.types.long;typedef.UMLong=ref.types.uint32;typedef.MFloat=ref.types.float;//提供C++结构定义方法constStructType=require('ref-struct');typedef.__tag_rect=StructType({left:typedef.MInt32,top:typedef.MInt32,right:typedef.MInt32,bottom:typedef.MInt32});//提供C++数组定义方法constArrayType=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]Activefileinformation]]}//一个是带回来调用函数letlibname=ffi.Library('./libname',{'setCallback':['void',['pointer']]});letcallback=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(大小);初始化指针:libc.memset(*p,offset,size);复制指针:libc.memcpy(*to,*from,size);7.在node中合并buffer,复制指针到bufferconstarr=newBuffer(TypeDef.MByte.size);for(leti=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)8、开源说明开源不易,使用代码时请注明出处,谢谢~如果觉得我的代码对你有帮助,请点赞支持,谢谢~想了解更多人脸识别产品,请前往虹软视觉开放平台
