人脸识别WEB登录

利用百度Api人脸识别实现WEB登录

思路:

  1. 对合法用户人脸进行注册。账号-人脸图片。
  2. 登录时采集用户人脸,上传服务器,调用百度API进行人脸比对。
  3. 符合相似率则认证成功,生成用户TOKEN返回。
  4. 否则认证失败。

注意:

  • chrome调用摄像头仅允许https。
  • 必要时可先进行活体检测

部分后台代码如下

1、注册百度账号,申请API
2、项目中引入百度SDK
官方文档:https://ai.baidu.com/ai-doc/FACE/Lk37c1tpf

        <!-- 人脸识别 sdk-->
        <dependency>
            <groupId>com.baidu.aip</groupId>
            <artifactId>java-sdk</artifactId>
            <version>4.15.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-simple</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

3、人脸识别工具类 FaceUtil.java


import com.baidu.aip.face.AipFace;
import com.baidu.aip.util.Base64Util;

/**
 * Desc: 人脸识别工具
 */
public class FaceUtil {
    private static final String APP_ID = "";
    private static final String APP_KEY = "";
    private static final String SECRET_KEY = "";

    private static volatile AipFace client = new AipFace(APP_ID, APP_KEY, SECRET_KEY);

    public static AipFace getClient(){
        client.setConnectionTimeoutInMillis(2000);
        client.setSocketTimeoutInMillis(60000);
        return client;
    }

    /**
     * 编码
     */
    public static String encodeBase64(byte[] form){
        return Base64Util.encode(form);
    }

    /**
     * 解码
     */
    public static byte[] decodeBase64(String data){
        return Base64Util.decode(data);
    }
}


人脸检测管理 FaceManage.java


import com.alibaba.fastjson.JSON;
import com.baidu.aip.face.FaceVerifyRequest;
import com.baidu.aip.face.MatchRequest;
import com.kaxinkeji.im.common.face.constant.ActionTypeEnum;
import com.kaxinkeji.im.common.face.constant.FaceConstant;
import com.kaxinkeji.im.common.face.constant.LivenessControlEnum;
import com.kaxinkeji.im.common.face.constant.QualityControlEnum;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;

@Service
public class FaceManage {
    private static final Logger logger = LoggerFactory.getLogger(FaceManage.class);

    /**
     * 人脸注册
     */
    public static void faceRegister(FaceUserDTO userDTO, ImageU imageU) {
        // 传入可选参数调用接口
        HashMap<String, String> options = new HashMap<String, String>();
        // 用户资料
        options.put("user_info", JSON.toJSONString(userDTO));
        // 图片质量
        options.put("quality_control", QualityControlEnum.LOW.name());
        // 活体检测控制
        options.put("liveness_control", LivenessControlEnum.NONE.name());
        // 操作方式
        options.put("action_type", ActionTypeEnum.REPLACE.name());

        String image = imageU.getData();
        String imageType = imageU.getImageTypeEnum().name();
        String groupId = userDTO.getGroupId();
        String userId = userDTO.getUserId();

        // 人脸注册
        JSONObject res = FaceUtil.getClient().addUser(image, imageType, groupId, userId, options);
        FaceResultUtil.isSuccess(res);
        logger.info("人脸注册成功");
    }


    /**
     * 人脸更新
     */
    public static void faceUpdate(FaceUserDTO userDTO, ImageU imageU) {
        HashMap<String, String> options = new HashMap<String, String>();
        // 用户资料
        options.put("user_info", JSON.toJSONString(userDTO));
        // 图片质量
        options.put("quality_control", QualityControlEnum.LOW.name());
        // 活体检测控制
        options.put("liveness_control", LivenessControlEnum.NONE.name());
        // 操作方式
        options.put("action_type", ActionTypeEnum.REPLACE.name());

        String image = imageU.getData();
        String imageType = imageU.getImageTypeEnum().name();
        String groupId = userDTO.getGroupId();
        String userId = userDTO.getUserId();

        // 人脸更新
        JSONObject res = FaceUtil.getClient().updateUser(image, imageType, groupId, userId, options);
        FaceResultUtil.isSuccess(res);
        logger.info("人脸更新成功 {}", res.toString(2));
    }


    /**
     * 人脸删除
     */
    public static void faceDelete(String userId, String groupId, String faceToken) {
        // 传入可选参数调用接口
        HashMap<String, String> options = new HashMap<String, String>();
        // 人脸删除
        JSONObject res = FaceUtil.getClient().faceDelete(userId, groupId, faceToken, options);
        FaceResultUtil.isSuccess(res);
        logger.info("人脸删除成功 {}", res.toString(2));
    }


    /**
     * 用户信息查询
     */
    public static FaceUserDTO<String> findUser(String userId, String groupId) {
        HashMap<String, String> options = new HashMap<>();
        // 用户信息查询
        JSONObject res = FaceUtil.getClient().getUser(userId, groupId, options);
        FaceResult result = FaceResultUtil.isSuccess(res);
        return JSON.parseObject(result.getData().toJSONString(), FaceUserDTO.class);
    }


    /**
     * 获取用户人脸列表
     *
     * @throws Exception
     */
    public static FaceResult faceGetList(String userId, String groupId) {
        HashMap<String, String> options = new HashMap<String, String>();
        // 获取用户人脸列表
        JSONObject res = FaceUtil.getClient().faceGetlist(userId, groupId, options);
        return FaceResultUtil.isSuccess(res);
    }


    /**
     * 获取用户列表
     */
    public static FaceResult listUserByGroupId(String groupId) {
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("start", "0");
        options.put("length", "50");
        // 获取用户列表
        JSONObject res = FaceUtil.getClient().getGroupUsers(groupId, options);
        return FaceResultUtil.isSuccess(res);
    }


    /**
     * 删除用户
     */
    public static void deleteUser(String userId, String groupId) {
        HashMap<String, String> options = new HashMap<String, String>();
        // 删除用户
        JSONObject res = FaceUtil.getClient().deleteUser(groupId, userId, options);
        FaceResultUtil.isSuccess(res);
        logger.info("用户删除成功 {}", res.toString(2));
    }


    /**
     * 创建用户组
     */
    public static void addGroup(String groupId) {
        HashMap<String, String> options = new HashMap<String, String>();
        // 创建用户组
        JSONObject res = FaceUtil.getClient().groupAdd(groupId, options);
        FaceResultUtil.isSuccess(res);
        logger.info("创建用户组 {}", res.toString(2));
    }


    /**
     * 删除用户组
     */
    public static void deleteGroup(String groupId) {
        HashMap<String, String> options = new HashMap<String, String>();
        // 删除用户组
        JSONObject res = FaceUtil.getClient().groupDelete(groupId, options);
        FaceResultUtil.isSuccess(res);
        logger.info("删除用户组 {}", res.toString(2));
    }

    /**
     * 组列表查询
     */
    public static FaceResult listGroup() {
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("start", "0");
        options.put("length", "50");
        // 组列表查询
        JSONObject res = FaceUtil.getClient().getGroupList(options);
        return FaceResultUtil.isSuccess(res);
    }


    /**
     * 身份验证
     */
    public static FaceResult personVerify(String idCardNumber, String realName, ImageU imageU) {
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("quality_control", QualityControlEnum.LOW.name());
        options.put("liveness_control", LivenessControlEnum.NONE.name());
        // 身份验证
        JSONObject res = FaceUtil.getClient().personVerify(imageU.getData(), imageU.getImageTypeEnum().name(), idCardNumber, realName, options);
        return FaceResultUtil.isSuccess(res);
    }

    /**
     * 人脸对比
     */
    public static int faceMatchScore(ImageU imageU1, ImageU imageU2) {
        MatchRequest req1 = new MatchRequest(imageU1.getData(), imageU1.getImageTypeEnum().name());
        MatchRequest req2 = new MatchRequest(imageU2.getData(), imageU2.getImageTypeEnum().name());
        ArrayList<MatchRequest> requests = new ArrayList<MatchRequest>();
        requests.add(req1);
        requests.add(req2);
        JSONObject res = FaceUtil.getClient().match(requests);
        FaceResult result = FaceResultUtil.isSuccess(res);
        // 对结果进行特殊处理
        Integer score = result.getData().getInteger(FaceConstant.SCORE);
        return score == null ? 0 : score;
    }


    /**
     * 人脸是否对比成功
     *
     * @param imageU1
     * @param imageU2
     * @param score   匹配分数
     * @return
     */
    public static boolean isfaceMatch(ImageU imageU1, ImageU imageU2, Integer score) {
        int defaultScore = FaceConstant.MATCH_SCORE;
        if (Objects.nonNull(score)) {
            defaultScore = score;
        }
        return faceMatchScore(imageU1, imageU2) > defaultScore ? true : false;
    }

    /**
     * 人脸检测
     */
    public static FaceResult faceDetect(ImageU imageU) {
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("face_field", "age");
        options.put("max_face_num", "2");
        options.put("face_type", "LIVE");
        // 人脸检测
        JSONObject res = FaceUtil.getClient().detect(imageU.getData(), imageU.getImageTypeEnum().name(), options);
        return FaceResultUtil.isSuccess(res);
    }


    /**
     * 人脸搜索
     */
    public static FaceResult faceSearch(String groupIds, ImageU imageU) {
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("max_face_num", "1");
        options.put("max_user_num", "1");
        options.put("quality_control", QualityControlEnum.LOW.name());
        options.put("liveness_control", LivenessControlEnum.NONE.name());
        // 人脸搜索
        JSONObject res = FaceUtil.getClient().search(imageU.getData(), imageU.getImageTypeEnum().name(), groupIds, options);
        return FaceResultUtil.isSuccess(res);
    }

    /**
     * 活体检测
     */
    public static FaceResult faceverify(ImageU imageU) {
        FaceVerifyRequest req = new FaceVerifyRequest(imageU.getData(), imageU.getImageTypeEnum().name());
        ArrayList<FaceVerifyRequest> list = new ArrayList<FaceVerifyRequest>();
        list.add(req);
        JSONObject res = FaceUtil.getClient().faceverify(list);
        return FaceResultUtil.isSuccess(res);
    }
}


部分前端代码如下:(web实现)

 window.onload = function (){
        try{
   document.createElement("canvas").getContext("2d");
            document.getElementById("support").innerHTML = "浏览器支持HTML5 CANVAS";
        }catch(e){
            document.getElementById("support").innerHTML = "浏览器不支持HTML5 CANVAS";
        }
    };

    //这段代 主要是获取摄像头的视频流并显示在Video 签中
    window.addEventListener("DOMContentLoaded", function () {
        var video = document.getElementById("video");
        var videoObj = { "video": true };
        var errBack = function (error){
            console.log("Video capture error: " + error.message, error.code);
        };
        //  支持浏览器  谷歌,火狐,360,欧朋
        // debugger;
        var constraints = { audio: true, video: { width: 1280, height: 720 } };

        navigator.mediaDevices.getUserMedia(constraints)
            .then(function(mediaStream) {
                var video = document.querySelector('video');
                video.srcObject = mediaStream;
                video.onloadedmetadata = function(e) {
                    video.play();
                };
            })
            .catch(function(err) { console.log(err.name + ": " + err.message); }); // always check for errors at the end.


        // navigator.getUserMedia = navigator.getUserMedia ||
        //     navigator.webkitGetUserMedia ||
        //     navigator.mozGetUserMedia;
        //
        //
        // if (navigator.getUserMedia) {
        //     navigator.getUserMedia({
        //             audio: true,
        //             video: {
        //                 width: 1280,
        //                 height: 720
        //             }
        //         },
        //         function(stream) {
        //             var video = document.querySelector('video');
        //             video.srcObject = stream;
        //             video.onloadedmetadata = function(e) {
        //                 video.play();
        //             };
        //         },
        //         function(err) {
        //             alert("The following error occurred: " + err.name);
        //         }
        //     );
        // } else {
        //     var div = document.createElement("div");
        //     div.innerHTML = 'getUserMedia not supported';
        //     document.body.appendChild(div);
        //     alert("getUserMedia not supported");
        // }

        //这个是拍照按钮的事件,
		document.getElementById("snap").addEventListener("click",function(){
             CatchCode();
        });
    }, false);

    function dataURItoBlob (base64Data) {
        var byteString;
        if (base64Data.split(',')[0].indexOf('base64') >= 0)
            byteString = atob(base64Data.split(',')[1]);
        else
            byteString = unescape(base64Data.split(',')[1]);
        var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];
        var ia = new Uint8Array(byteString.length);
        for (var i = 0; i < byteString.length; i++) {
            ia[i] = byteString.charCodeAt(i);
        }
        return new Blob([ia], {type: mimeString});
    };

    //定时器
    //var interval = setInterval(CatchCode, "300");
    
    
    function CatchCode() {
        var canvans = document.getElementById("canvas");
        var video = document.getElementById("video");
        var context = canvas.getContext("2d");

        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        context.drawImage(video,0,0);

        var base64Data = canvans.toDataURL("image/jpeg", 0.3);
        //封装blob对象
        var blob = dataURItoBlob(base64Data);

        var formdata = new FormData();
        formdata.append("file", blob);

        $.ajax({
            url: "/api/login_face",
            type: "post",
            data:formdata,
            processData: false,
            contentType: false,
            success: function (data) {
                console.log(data);
            },
            error:function(err){
                alert("服务器错误");
            }
        });
    }
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐