简简单单,带你撸个人脸识别登录

近期研究很多种登录系统的方式,有邮箱、手机号、QQ、微博、人脸登录等。整合了一下,用SpringBoot写了个简单的小Demo,供大家学习参考。之后在编写项目的时候你就可以选择性整合进去了,可以稍微提升一下项目B格。

这期文章先讲一下我觉得挺好玩的人脸登录,我用的是百度云的人脸识别服务。实现的效果如下:

简简单单,带你撸个人脸识别登录_第1张图片

简简单单,带你撸个人脸识别登录_第2张图片

登录百度云创建应用

即然我们用到的是百度云的服务,那么我们首选需要登录百度云的官网

https://console.bce.baidu.com/

注册登录之后好像需要实名认证,认证一下就OK了,很快。

之后我们可以直接在控制台总览搜索【人脸识别】,点击进入

简简单单,带你撸个人脸识别登录_第3张图片

进入之后创建应用,填写应用的信息,应用归属选择个人即可,创建完成之后,我们还需要领取一下免费资源。

简简单单,带你撸个人脸识别登录_第4张图片

然后我们选择管理应用,就可以看到我们所创建应用的AppID、API Key和Secret Key了,这三个信息是我们项目调用服务的关键配置。

后端核心逻辑

Lock lock = new ReentrantLock();

/**
 * 人脸登录注册
 */
@PostMapping("/loginByFace")
@ResponseBody
public ResponseResult loginByFace(String data, HttpSession session) {
    String base64Prefix = "data:image/png;base64,";
    if (StrUtil.isEmpty(data)) {
        return ResponseResult.failure(ResponseCode.PARAMETER_ERROR);
    }
    if (data.startsWith(base64Prefix)) {
        data = data.substring(base64Prefix.length());
    }
    lock.lock();
    // 判断是否存在人脸库
    ResponseResult searchByBase64 = faceService.searchByBase64(data);
    if (searchByBase64.getCode() == 0) {
        // 存在人脸库,登录成功
        JSONObject result = (JSONObject) searchByBase64.getData();
        Integer id = Integer.valueOf(result.get("user_id") + "");
        session.setAttribute("user", userService.get(id));
        lock.unlock();
        return new ResponseResult(0, "登录成功", null);
    }
    // 不存在人脸库,则自动注册
    ResponseResult detectByBase64 = faceService.detectByBase64(data, true);
    if (detectByBase64.getCode() != 0) {
        lock.unlock();
        return detectByBase64;
    }
    Map<String, String> map = (Map<String, String>) detectByBase64.getData();
    String faceToken = map.get("face_token");
    // 注册用户
    User user = User.builder()
            .faceId(faceToken)
            .img("https://moti-cloud-v2.oss-cn-beijing.aliyuncs.com/%E4%BA%BA%E8%84%B8%E8%AF%86%E5%88%AB_o.png")
            .faceId(faceToken)
            .name("注册用户" + DateTime.now())
            .build();
    userService.save(user);
    session.setAttribute("user", user);
    faceService.registryByFaceToken(faceToken, user.getId() + "");
    lock.unlock();
    return ResponseResult.success();
}

前端程序编写

前端我也封装也了一个js文件,把人脸识别需要的方法统一放在此处。

/*
    人脸登录相关方法
 */

//  定义变量
let streams;
let timers = null;
let send;
let loginUrl = "loginByFace";
let video = document.getElementById('face-video');
let canvas = document.getElementById('face-canvas');
let context = canvas.getContext('2d');

/**
 * 发送视频图片
 */
function sendImg() {
    timers = setInterval(function () {
        if (send) {
            send = false;
            context.drawImage(video, 0, 0, 480, 320);
            let image = canvas.toDataURL('image/png');
            $.ajax({
                type: "POST",
                url: loginUrl,
                data: {
                    data: image,
                },
                dataType: "json",
                success: function (data) {
                    console.log(data);
                    if (data['code'] === 0) {
                        layer.msg("登录成功");
                        setTimeout("new function(){window.location.href= '/success'}",1000);
                    } else {
                        layer.msg(data['msg'])
                        send = true
                    }
                }
            });
        }
    }, 2000);
}

/**
 * 开启摄像头
 */
function openCamera() {
    try {
        if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
            // 调用用户媒体设备, 访问摄像头
            getUserMedia({video: {width: 480, height: 320}}, successCallBack, errorCallBack);
        } else {
            alert("启动摄像头失败");
        }
    } catch (err) {
        alert("受限于浏览器安全策略,无法启动摄像头");
    }
}

/**
 * 关闭摄像头
 */
function closeCamera() {
    if (streams !== undefined) {
        streams.stop();
    }
    if (!timers) {
        clearInterval(timers);
    }
}

/**
 * 访问用户媒体设备的兼容方法
 * @param constraints
 * @param success 成功回调
 * @param error 失败回调
 */
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) {
        // firefox浏览器
        navigator.mozGetUserMedia(constraints, success, error);
    } else if (navigator.getUserMedia) {
        // 旧版API
        navigator.getUserMedia(constraints, success, error);
    }
}

/**
 * 成功回调
 * @param stream
 */
function successCallBack(stream) {
    // 兼容webkit核心浏览器
    let CompatibleURL = window.URL || window.webkitURL;
    // 将视频流设置为video元素的源
    streams = stream.getTracks()[0];
    video.srcObject = stream;
    video.play();
    send = true;
    sendImg();
}

/**
 * 失败回调
 * @param error
 */
function errorCallBack(error) {
    alert(`访问媒体设备失败: ${error.message}`);
}

之后只需要在前端HTML中加上显示面板即可

实现思路

这个示例中,我们只是作为一个服务的使用者,具体如何使用,那么服务的提供方(百度云),已经提供了非常详细的文件。那么下一步我就就需要找到我们具体所用到的这些接口的文档,详加研究,需要什么参数,我们获取到并且传递给它即可。

更方便的是官方已经帮我们封装好了SDK,相当于提供了工具类,那么我们只需要学习怎么用这个工具类就行了。

https://cloud.baidu.com/doc/FACE/s/8k37c1rqz

简简单单,带你撸个人脸识别登录_第5张图片

这个示例主要用到了人脸检测、人脸搜索、人脸注册服务,每个服务具体怎么用可以看官网的示例,这里就不做解释了。

大多数服务都需要我们基于人脸的图片去操作和调用,官方给到的图片类型有三种:BASE64字符串、URL字符串、FACE_TOKEN字符串。那么示例中使用的是BASE64字符串进入图片数据的传输。

那么有些人可能不太理解这个Base64是个什么东西,通俗点说就是它把二进制文件转成了可以打印的字符串,这是一种编码方式。

那么后面我们需要做的就是前端调用摄像头,抓取画面内容,将数据内容转为BASE64格式,访问后端接口将数据传递到后端,后端接收到数据后,调用官方的SDK,访问所需要的服务完成调用。

简简单单,带你撸个人脸识别登录_第6张图片

在这些关键步骤的中间会穿插着业务相关的内容,比如没有搜索到人脸后的处理(本示例是自动注册),以及搜索都结果后调用数据库,查询用户的详细信息、以及前端如何调用摄像头,如何连续像后端发送人脸登录请求等。

需要注意的细节还是不少的,但是核心的思路就是上面这些。

那么这个就是所谓的人脸登录了,挺好玩的吧!

获取项目开源地址:微信搜索【薛伟同学】,后台回复【人脸识别】


你可能感兴趣的:(SpringBoot,人脸登录)