美文网首页
还在用密码登录?快来试试离线人脸登录吧

还在用密码登录?快来试试离线人脸登录吧

作者: 爪哇日记 | 来源:发表于2020-04-08 11:42 被阅读0次

基于虹软的离线人脸识别

  • 注册虹软账号,获取离线SDK
  • 自定义人脸库(保存人脸关键点信息),并添加人脸到人脸库
  • 获取登录客户的人脸
  • 使用SDK解析人脸,获取关键点信息
  • 登录人脸信息 与人脸库比对 比对成功或失败(对应登录成功或失败)

人脸识别示例:

  • 添加用户(成功后提示,并在数据库插入一条数据)


    在这里插入图片描述
    在这里插入图片描述
  • 查找用户(匹配成功后回填用户信息,可以根据业务跳转登录)
    在这里插入图片描述

获取虹软SDK

先在 虹软官网 登录开发者账号(没有账号先注册后再登录)


创建人脸识别应用

在这里插入图片描述
创建SDK(以windows为例)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
SKD包文件内容
在这里插入图片描述

人脸识别工具类   创建FaceEngine 引擎时要指定依赖文件路径(为sdk压缩包中 libs文件夹下的dll文件路径)

package com.face.facetest.utils;

import com.arcsoft.face.*;
import com.arcsoft.face.enums.DetectMode;
import com.arcsoft.face.enums.DetectOrient;
import com.arcsoft.face.enums.ErrorInfo;
import com.arcsoft.face.toolkit.ImageInfo;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

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

/**
 * @Auther: zs
 * @Date: 2020/4/7 15:51
 * @Description:
 */
@Data
@Component
public class FaceUtils {

    @Value("${face.appId}")
    private String appId1;
    @Value("${face.sdkKey}")
    private String sdkKey1;

    public static String appId;
    public static String sdkKey;

    @PostConstruct
    public void init(){
        appId = this.appId1;
        sdkKey = this.sdkKey1;
    }

    //特征比对
    public static float compare(FaceEngine faceEngine,byte[] sources,byte[] target){
        FaceFeature targetFaceFeature = new FaceFeature();
        targetFaceFeature.setFeatureData(target);
        FaceFeature sourceFaceFeature = new FaceFeature();
        sourceFaceFeature.setFeatureData(sources);
        FaceSimilar faceSimilar = new FaceSimilar();
        int errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
        return faceSimilar.getScore();
    }

    //特征
    public static byte[] feature(FaceEngine faceEngine,byte[] bytes,FaceInfo faceInfo){
        ImageInfo imageInfo = getRGBData(bytes);
        //特征提取
        FaceFeature faceFeature = new FaceFeature();
        int errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfo, faceFeature);
        System.out.println("特征值大小:" + faceFeature.getFeatureData().length);
        return faceFeature.getFeatureData();
    }

    //获取人脸位置
    public static List<FaceInfo> detectFaces(FaceEngine faceEngine,byte[] bytes){
        //人脸检测
        ImageInfo imageInfo = getRGBData(bytes);
        List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
        int errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
        return faceInfoList;
    }


    public static FaceEngine getFaceEngine(){

        /*
        * 此路径为sdk压缩包中 libs文件夹下的dll文件路径
        * */
        FaceEngine faceEngine = new FaceEngine("C:\\Users\\zs\\Desktop\\ArcSoft\\arcsoft_lib");
        //激活引擎
        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(16);
        //功能配置
        FunctionConfiguration functionConfiguration = new FunctionConfiguration();
        functionConfiguration.setSupportAge(true);
        functionConfiguration.setSupportFace3dAngle(true);
        functionConfiguration.setSupportFaceDetect(true);
        functionConfiguration.setSupportFaceRecognition(true);
        functionConfiguration.setSupportGender(true);
        functionConfiguration.setSupportLiveness(true);
        functionConfiguration.setSupportIRLiveness(true);
        engineConfiguration.setFunctionConfiguration(functionConfiguration);


        //初始化引擎
        errorCode = faceEngine.init(engineConfiguration);

        if (errorCode != ErrorInfo.MOK.getValue()) {
            System.out.println("初始化引擎失败");
        }
        return faceEngine;
    }
}

注意:人脸识别的jar包需要添加依赖后才可正常使用,否则会报异常。springboot项目jar报启动时 可在:File->Project Structure->Modular 下添加依赖

在这里插入图片描述
数据库
在这里插入图片描述
保存人脸信息-页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/css/common.css" media="all">
</head>
<body class="align-center">

    <h1 style="margin-top: 50px">添加用户信息</h1>
    <br>
    <div class="faceDiv">
        <video id="video"></video>
        <canvas id="canvas" style="display: none;"></canvas>
    </div>
    <br/><br/><br/>
    用户名:<input id="name" />
    <br/><br/><br/>
    <button id="saveUser">保存</button>
</body>
<script src="/js/jquery-3.4.1.min.js" charset="utf-8"></script>
<script src="/js/face.js" charset="utf-8"></script>
<script>
    openUserMedia();

    $("#saveUser").click(function () {
        var name = $("#name").val();
        if(name){
            var img = getFace();
            $.ajax({
                type:"post",
                url:"/addUser",
                data:{
                    "faceStr":img,
                    "name":name
                },
                success:function (rst) {
                    alert(rst.msg)
                },
                error:function () {
                    alert("连接服务器失败")
                }
            })
        }else{
            alert("姓名不能为空")
        }


    })
</script>
</html>
在这里插入图片描述
查找人脸信息-页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/css/common.css" media="all">
</head>
<body class="align-center">

    <h1 style="margin-top: 50px">查找用户信息</h1>
    <br>
    <div class="faceDiv">
        <video id="video"></video>
        <canvas id="canvas" style="display: none;"></canvas>
    </div>
    <br/><br/><br/>
    用户信息:<span id="userInfo"></span>
    <br/><br/><br/>
    <button id="searchUser">查找</button>
</body>
<script src="/js/jquery-3.4.1.min.js" charset="utf-8"></script>
<script src="/js/face.js" charset="utf-8"></script>
<script>
    openUserMedia();

    $("#searchUser").click(function () {
        var img = getFace();
        $.ajax({
            type:"post",
            url:"/searchUser",
            data:{
                "faceStr":img
            },
            success:function (rst) {
                $("#userInfo").html(rst.msg)
            },
            error:function () {
                alert("连接服务器失败")
            }
        })

    })
</script>
</html>
在这里插入图片描述
页面获取摄像头JS(页面引用的face.js)

//成功回调函数
var video = document.getElementById("video");
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var mediaStreamTrack=null;
function success(stream){
    //兼容webkit核心浏览器
    //将视频流转化为video的源
    mediaStreamTrack=stream;
    try {
        // video.src = CompatibleURL.createObjectURL(stream);
        video.srcObject=stream;
    }catch (e) {
        console.log("访问用户媒体设备失败:",error.name,error.message);
    }

    video.play();//播放视频
}
//错误回调函数
function error(error) {
    console.log('访问用户媒体失败:',error.name,error.message);
}
function getUserMediaToPhoto(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){
        //firefox浏览器
        navigator.mozGetUserMedia(constraints,success,error);
    }else if(navigator.getUserMedia){
        //旧版API
        navigator.getUserMedia(constraints,success,error);
    }
}
//获取图片
function getFace() {
    context.drawImage(video,0,0,300,150);
    this.img=canvas.toDataURL('image/jpg')
    //获取完整的base64编码
    this.img=img.split(',')[1];
    return this.img;
}
//打开摄像头
function openUserMedia() {
    if(navigator.mediaDevices.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia){
        getUserMediaToPhoto({video:{width:300,height:300,facingMode: "user"}},success,error);
    }else{
        alert('你的浏览器不支持访问用户媒体设备');
    }
}
//关闭摄像头
function  offUserMedia() {
    if(mediaStreamTrack!=null)
        mediaStreamTrack.getTracks()[0].stop();
}




后台Controller

package com.face.facetest.controller;

import com.arcsoft.face.FaceEngine;
import com.arcsoft.face.FaceInfo;
import com.face.facetest.service.FaceInfoServiceImpl;
import com.face.facetest.utils.FaceUtils;
import com.face.facetest.utils.ImageUtils;
import com.face.facetest.vo.FaceVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;

/**
 * @Auther: zs
 * @Date: 2020/4/7 15:47
 * @Description:
 */
@RestController
public class IndexController {
    @Autowired
    private FaceInfoServiceImpl faceInfoService;

    @RequestMapping("/addUser")
    public Object addUser(HttpServletRequest request, FaceVo faceVo){
        HashMap<Object, Object> result = new HashMap<>();
        result.put("msg","异常");
        if(faceVo.getFaceStr() != null && faceVo.getName() != null){
            byte[] bytes = ImageUtils.base64ToByte(faceVo.getFaceStr());
            FaceEngine faceEngine = FaceUtils.getFaceEngine();
            List<FaceInfo> faceInfos = FaceUtils.detectFaces(faceEngine, bytes);
            if(faceInfos != null && faceInfos.size() > 0){
                byte[] feature = FaceUtils.feature(faceEngine, bytes, faceInfos.get(0));
                com.face.facetest.entry.FaceInfo faceInfo = new com.face.facetest.entry.FaceInfo();
                faceInfo.setName(faceVo.getName());
                faceInfo.setFaceData(feature);
                boolean save = faceInfoService.save(faceInfo);
                if(save){
                    result.put("msg","添加成功");
                }
            }
            faceEngine.unInit();
        }
        return result;
    }


    @RequestMapping("/searchUser")
    public Object searchUser(HttpServletRequest request, FaceVo faceVo){
        HashMap<Object, Object> result = new HashMap<>();
        result.put("msg","异常");
        if(faceVo.getFaceStr() != null){
            byte[] bytes = ImageUtils.base64ToByte(faceVo.getFaceStr());
            FaceEngine faceEngine = FaceUtils.getFaceEngine();
            List<FaceInfo> faceInfos = FaceUtils.detectFaces(faceEngine, bytes);
            if(faceInfos != null && faceInfos.size() > 0){
                byte[] feature = FaceUtils.feature(faceEngine, bytes, faceInfos.get(0));
                if(feature != null){
                    List<com.face.facetest.entry.FaceInfo> list = faceInfoService.list();
                    if(list != null){
                        for (com.face.facetest.entry.FaceInfo faceInfo : list) {
                            if(faceInfo.getFaceData() != null){
                                float compare = FaceUtils.compare(faceEngine, feature, faceInfo.getFaceData());
                                if(compare >= 0.8){
                                    result.put("msg",faceInfo.getName());
                                }
                            }
                        }
                    }
                }

            }
            faceEngine.unInit();
        }
        return result;
    }
}

流程总结:

人脸识别流程(添加用户):

  • 页面获取头像
  • 后台获取头像,SDK解析获取关键点信息
  • 保存数据库

人脸识别流程(查找用户):

  • 获取头像信息
  • 后台获取头像,SDK解析获取关键点信息
  • 获取头像库的信息,比对相似值(官方推荐获取相似值大于0.8的),并获取用户唯一标识(此处名称为唯一标识,可根据业务自行指定)
  • 根据唯一标示获取用户信息
  • 根据用户信息按正常的登录流程走就可以了

项目下载地址:https://github.com/15225845996/face-test.git

搜索公众号:【爪哇日记】关注最新文章

在这里插入图片描述

相关文章

网友评论

      本文标题:还在用密码登录?快来试试离线人脸登录吧

      本文链接:https://www.haomeiwen.com/subject/rezznqtx.html