使用虹软SDK实现离线人脸识别(局域网)

第一步,获取SDK
首先注册开发者账号,创建一个应用,得到两个东西,用于激活SDK引擎的,SDK key 和 AppID。

把SDK下载到本地,我这里选择的是java版本的, 文件夹中包括开发者文档、API文档、示例程序、jar包、引擎库dll文件。

第二步,写后台

把文件夹中的jar包复制到项目中的lib(自己创建的)文件夹下,

依赖这样写:

		<dependency>
			<groupId>com.arcsoft.face</groupId>
			<artifactId>arcsoft-sdk-face</artifactId>
			<version>3.0.0.0</version>
			<scope>system</scope>
			<systemPath>${basedir}/src/main/resources/lib/arcsoft-sdk-face-3.0.0.0.jar</systemPath>
		</dependency

 前端html以及js

       chooseBorrower:function(){
            var _this = this;
            layer.open({
                type: 2,
                offset: 'auto',
                skin: 'layui-layer-lan',
                title: "选择关键词",
                area: ['88%', '100%'],
                shade: 0.3,
                shadeClose: false,
                content: '../borrow/borrower_choose.html',
                btn: ['确定','取消'],//'确定',
                yes: function(index, layero){
                    var mkey = layero.find("iframe")[0].contentWindow.$("#ids").val();
                    var mkeyName = layero.find("iframe")[0].contentWindow.$("#names").val();
                    if(mkey && mkey!=""){
                        var faceshow=$("#faceshow").val();
                       if(faceshow){
                       //人脸识别步骤
                        _this.getSfz(mkey,mkeyName);
                       }else{
                       //非人脸步骤
                        _this.setNameword(mkey,mkeyName);
                       }
                      layer.closeAll();
                   }else{
                        layer.alert("请选择关键词");
                        return;
                    }
                }
            });
        },
        getSfz:function(mkey,mkeyName){
            var _this = this;
            var url ="face/analysis/getSfz";
            $.ajax({
                data:{id: mkey},
                type: "POST",
                url: baseURL + url,
                success: function (r) {
                    if(r.code==0) {
                        _this.sfz= r.msg;
                        layer.open({
                            type: 2,
                            offset: 'auto',
                            skin: 'layui-layer-lan',
                            title: "人脸识别",
                            area: ['460px', '380px'],
                            shade: 0.3,
                            shadeClose: false,
                            content: '../face/faceIndex.html',
                            end: function(){
                                _this.setNameword(mkey,mkeyName);
                            }
                        });
                    }else{
                        alert(r.msg);
                    }
                }
            });
        },

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>拍照上传</title>
    <#include "/header.html">
    <link rel="stylesheet" href="${request.contextPath}/statics/css/face.css">
</head>
<body>
<div class="index__tips" id="index__tips"></div>
<div class="index__video-panel">
    <!-- 显示摄像头拍摄到的视频 -->
    <video id="index__video" class="index__video"></video>
    <!-- 视频上的提示框 -->
    <svg width="200" height="200" class="index__video-over">
        <!-- 克莱因蓝 #002FA7 -->
        <polyline points="5,50 5,5 50,5" fill-opacity="0"
                  style="stroke:#002FA7;stroke-width:10"/>
        <polyline points="5,150 5,195 50,195" fill-opacity="0"
                  style="stroke:#002FA7;stroke-width:10"/>
        <polyline points="155,5 195,5 195,45" fill-opacity="0"
                  style="stroke:#002FA7;stroke-width:10"/>
        <polyline points="155,195 195,195 195,155" fill-opacity="0"
                  style="stroke:#002FA7;stroke-width:10"/>
    </svg>
</div>
<!-- 用于给video标签截图的画布 -->
<canvas id="index__canvas" style="display:none;"></canvas>
<div id="rrapp" v-cloak>
<input type="hidden" id="sfz" v-model="sfz"/>
</div>
<script src="${request.contextPath}/statics/libs/axios.min.js?_${.now?long}"></script>
<script type="text/javascript" src="${request.contextPath}/statics/js/modules/face/face.js?_${.now?long}"></script>
</body>
</html>
/**
 * 拍照上传图片
 */
var indexObj = {};

indexObj.tips = "没有检测到设备,请确保开启摄像头!";

debugger
//首次运行引导用户,信任域名
var first = window.localStorage.getItem('first');
if(first == null ){
    if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
        //调用用户媒体设备, 访问摄像头
        getUserMedia({video: {width: 480, height: 320}}, success, error);
    } else {
        alert('不支持访问用户媒体');
    }
}


//访问用户媒体设备的兼容方法
function getUserMedia(constraints, success, error) {
    if (navigator.mediaDevices.getUserMedia) {
        //最新的标准API
        navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
    } else if (navigator.webkitGetUserMedia) {
        //webkit核心浏览器
        navigator.webkitGetUserMedia(constraints, success, error)
    } else if (navigator.mozGetUserMedia) {
        //firfox浏览器
        navigator.mozGetUserMedia(constraints, success, error);
    } else if (navigator.getUserMedia) {
        //旧版API
        navigator.getUserMedia(constraints, success, error);
    }
}

var video = document.getElementById('index__video');

function success(stream) {
    //兼容webkit核心浏览器
    var CompatibleURL = window.URL || window.webkitURL;
    //将视频流设置为video元素的源
    video.srcObject = stream;
    // video.play();
    video.onloadedmetadata = function (e) {
        video.play();
    };
}

function error(error) {
    document.getElementById("index__tips").innerHTML = indexObj.tips;
}


// 列出摄像头和麦克风
var exArray = [];
navigator.mediaDevices.enumerateDevices().then(function (devices) {
    devices.forEach(function (device) {
        if (device.kind == "videoinput") {
            exArray.push(device.deviceId);
        }

    });
    var mediaOpts = {video: {deviceId: {exact: exArray[1]}}};
    //调用用户媒体设备, 访问摄像头
    getUserMedia(mediaOpts, success, error);

}).catch(function (err) {
    console.log(err.name + ": " + err.message);
});


/**
 * 拍照上传按钮的事件响应
 */

indexObj.uploadImg = function () {
    var canvas = document.getElementById("index__canvas");
    var video = document.getElementById("index__video");
    if (0 == video.videoWidth) {
        document.getElementById("index__tips").innerHTML = indexObj.tips;
        return;
    }
    // 让canvas和视频一样宽高。
    var w = video.videoWidth;
    var h = video.videoHeight;
    canvas.width = w;
    canvas.height = h;
    // 把video标签中的画面,画到canvas中。
    var ctx = canvas.getContext('2d');
    ctx.drawImage(video, 0, 0, w, h);
    // 把canvas中的图像转换成png图片文件的Base64字符串。
    var imgStr = canvas.toDataURL('image/png').split("base64,")[1];
    // 获得用户ID
    var sfz = document.getElementById("sfz").value;
    axios.post(baseURL+"face/analysis/upload", {"sfz": sfz, "imgStr": imgStr}).then(function (res) {
        var r=res.data;
        if(r.code==500){//人脸不匹配
            //alert(r.msg);
        } else{
            window.clearInterval(t1);
            parent.layer.closeAll();
            parent.alert("人脸匹配成功!");
        }
    }).catch(function (error) {
        console.error(error);
    })
}
var vm = new Vue({
    el:'#rrapp',
    data:{
        sfz:'',
    },
    created: function(){
        this.sfz=parent.getSfzParam();
    },
    methods: {
        getUrlKey:function(name){
            return decodeURIComponent((new RegExp('[?|&]'+name+'='+'([^&;]+?)(&|#|;|$)').exec(location.href)||[,""])[1].replace(/\+/g,'%20'))||null;
        },
    }
});
var t1=setInterval(indexObj.uploadImg, 1000 * 1);

Controller

package com.framework.modules.face.controller;

import com.arcsoft.face.*;
import com.arcsoft.face.enums.ErrorInfo;
import com.arcsoft.face.toolkit.ImageInfo;
import com.framework.common.config.FaceApiConfig;
import com.framework.common.config.SysBaseConfig;
import com.framework.common.utils.FaceUtils;
import com.framework.common.utils.FileUtils;
import com.framework.common.utils.R;
import com.framework.common.utils.StringUtils;
import com.framework.modules.borrow.entity.BorrowerEntity;
import com.framework.modules.borrow.service.BorrowerService;
import com.framework.modules.face.entity.ProfileUpload;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;

@RestController
@RequestMapping("face/analysis")
public class AnalysisController {
        @Autowired
        private FaceApiConfig faceApiConfig;
        @Autowired
        private SysBaseConfig sysBaseConfig;
        @Autowired
        private BorrowerService borrowerService;

        /**
         * 获取身份证照片路径
         */
        @RequestMapping("/getSfz")
        public R getSfz(@RequestParam(value = "id") String id) throws IOException {
                //根据ID拿到身份证
                BorrowerEntity borrower = borrowerService.selectById(id);
                if (borrower == null) {
                        return R.error("无此借阅人相关信息!");
                }
                String sfz = borrower.getSfz();
                if (sfz == null || "".equals(sfz)) {
                        return R.error("此借阅人无相关证件照片");
                }
                return R.ok(sfz);
        }


        @RequestMapping("/upload")
        public R upload(@RequestBody ProfileUpload profileUpload){
                StringBuffer fileName = new StringBuffer();
                fileName.append(UUID.randomUUID().toString().replaceAll("-", ""));
                if (StringUtils.isBlank(profileUpload.getImgStr())) {
                      return R.error("无识别视频!");
                }

                try {
                        FileUtils.createFile(profileUpload.getImgStr(),new File(faceApiConfig.getMat() + "//face.png"));
                        float score = this.analysis(profileUpload.getSfz());//匹配分数
                        if (score > 0.82) {//匹配通过
                                return R.ok("人脸匹配通过");
                        } else {
                                if (score == 0) {//人脸不匹配
                                        return R.error("检测结果为非活体");
                                } else {
                                        if (score != -3.0) {
                                                return R.error("人脸识别有误,请重试!");
                                        }
                                }
                        }
                } catch (Exception e) {
                   e.printStackTrace();
                }
                return R.error("人脸识别有误,请重试!");
        }

        private float analysis(String sfz) throws IOException {
                FaceEngine faceEngine= FaceUtils.getFaceEngine(faceApiConfig.getAppId(),faceApiConfig.getSdkKey());
                if(faceEngine==null){return -4;}//引擎初始化异常
                //人脸检测
                ImageInfo imageInfo = getRGBData(new File(sysBaseConfig.getProfile()+sfz));
                List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
                int errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);

                //特征提取
                FaceFeature faceFeature = new FaceFeature();
                errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
                errorCode = FaceUtils.unInit(faceEngine);//卸载引擎

                File f=new File(faceApiConfig.getMat()+"//face.png");
                if(f==null||!f.exists()){
                        return -3;
                }
                //人脸检测2
                ImageInfo imageInfo2 = getRGBData(f);
                faceEngine=FaceUtils.getFaceEngine(faceApiConfig.getAppId(),faceApiConfig.getSdkKey());
                List<FaceInfo> faceInfoList2 = new ArrayList<FaceInfo>();
                errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(),imageInfo2.getImageFormat(), faceInfoList2);

                //特征提取2
                FaceFeature faceFeature2 = new FaceFeature();
                errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2.get(0), faceFeature2);
                //特征比对
                FaceFeature targetFaceFeature = new FaceFeature();
                targetFaceFeature.setFeatureData(faceFeature.getFeatureData());
                FaceFeature sourceFaceFeature = new FaceFeature();
                sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData());
                FaceSimilar faceSimilar = new FaceSimilar();
                errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);

                //设置活体测试
                errorCode = faceEngine.setLivenessParam(0.5f, 0.7f);

                FunctionConfiguration configuration = new FunctionConfiguration();
                configuration.setSupportLiveness(true);
                configuration.setSupportFace3dAngle(true);
                errorCode = faceEngine.process(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2, configuration);

                //3D信息检测
                List<Face3DAngle> face3DAngleList = new ArrayList<Face3DAngle>();
                errorCode = faceEngine.getFace3DAngle(face3DAngleList);
                if(face3DAngleList == null || face3DAngleList.size() == 0) {
                        return errorCode;
                }
                //活体检测
                List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
                int livecode = faceEngine.getLiveness(livenessInfoList);
                //引擎卸载
                errorCode =FaceUtils.unInit(faceEngine);
                if(livecode== ErrorInfo.MOK.getValue()&&livenessInfoList.size()>0){
                        if(livenessInfoList.get(0).getLiveness()==1){
                                return faceSimilar.getScore();
                        }else{
                                return livenessInfoList.get(0).getLiveness();
                        }
                }
                return livecode;
        }

}

秘钥配置

@Configuration
@ConfigurationProperties(prefix="face.api")
public class FaceApiConfig {
	private String appId;
	private String sdkKey;
	private String mat;
	public String getAppId() {
		return appId;
	}

	public void setAppId(String appId) {
		this.appId = appId;
	}

	public String getSdkKey() {
		return sdkKey;
	}

	public void setSdkKey(String sdkKey) {
		this.sdkKey = sdkKey;
	}

	public String getMat() {
		return mat;
	}

	public void setMat(String mat) {
		this.mat = mat;
	}
}

人脸识别 引擎配置FaceUtils 

package com.framework.common.utils;

import com.arcsoft.face.ActiveFileInfo;
import com.arcsoft.face.EngineConfiguration;
import com.arcsoft.face.FaceEngine;
import com.arcsoft.face.FunctionConfiguration;
import com.arcsoft.face.enums.DetectMode;
import com.arcsoft.face.enums.DetectOrient;
import com.arcsoft.face.enums.ErrorInfo;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import java.io.File;
public class FaceUtils {
    public static FaceEngine getFaceEngine (String appId,String sdkKey){
        try {
            Resource resource = new ClassPathResource("");
            File file = new File(resource.getFile().getAbsolutePath());
            String path = file.getAbsolutePath() +  "/dll/arcsoft_lib";
            com.arcsoft.face.FaceEngine faceEngine = new com.arcsoft.face.FaceEngine(path);
            //激活引擎
            int errorCode = faceEngine.activeOnline(appId, sdkKey);
            if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
                System.out.println("引擎激活失败");
            }
            ActiveFileInfo activeFileInfo=new ActiveFileInfo();
            errorCode = faceEngine.getActiveFileInfo(activeFileInfo);
            if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
                System.out.println("获取激活文件信息失败");
            }
            //引擎配置
            EngineConfiguration engineConfiguration = new EngineConfiguration();
            engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
            engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
            engineConfiguration.setDetectFaceMaxNum(10);
            engineConfiguration.setDetectFaceScaleVal(32);
            engineConfiguration.setFunctionConfiguration(functionConfiguration());
            //初始化引擎
            errorCode = faceEngine.init(engineConfiguration);
            if (errorCode != ErrorInfo.MOK.getValue()) {
                System.out.println("初始化引擎失败");
            }
            return faceEngine;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    public static int unInit(FaceEngine faceEngine){//卸载引擎
        return faceEngine.unInit();
    }

    public static FunctionConfiguration functionConfiguration() {
        FunctionConfiguration functionConfiguration=new FunctionConfiguration();
        functionConfiguration.setSupportFaceDetect(true);
        functionConfiguration.setSupportFaceRecognition(true);
        functionConfiguration.setSupportLiveness(true);
        functionConfiguration.setSupportIRLiveness(true);
        functionConfiguration.setSupportAge(true);
        functionConfiguration.setSupportFace3dAngle(true);
        functionConfiguration.setSupportGender(true);
        return functionConfiguration; //该对象为Jar包对象
    }
}

此文章只供参考

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值