Java人脸识别登录案例(基于百度人脸识别AI)

Demo目录

在这里插入图片描述

配置百度人脸识别秘钥

在这里插入图片描述

获取秘钥,注册登录百度云账户

在人脸识别处创建应用,
AppID
API Key
Secret Key
groupId填入到配置文件

在这里插入图片描述
在这里插入图片描述

封装的一些方法

也可以根据源码再次封装方便使用

package com.example.demo.util;

import com.baidu.aip.face.AipFace;
import com.baidu.aip.face.FaceConsts;
import com.baidu.aip.http.AipRequest;
import com.baidu.aip.http.EBodyFormat;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;

@Component
public class BaiduAiUtil {

    @Value("${ai.appId}")
    private String APP_ID;
    @Value("${ai.apiKey}")
    private String API_KEY;
    @Value("${ai.secretKey}")
    private String SECRET_KEY;
    @Value("${ai.imageType}")
    private String IMAGE_TYPE;
    @Value("${ai.groupId}")
    private String groupId;

    private AipFace client;

    private HashMap<String, String> options = new HashMap<String, String>();

    public BaiduAiUtil() {
        options.put("quality_control", "NORMAL");
        options.put("liveness_control", "LOW");
    }

    @PostConstruct
    public void init() {
        client = new AipFace(APP_ID, API_KEY, SECRET_KEY);
    }

    //判断用户是否注册了面部信息
    public Boolean faceExist(String userId){
        JSONObject res=client.getUser(userId,groupId,null);
        Integer errorCode=res.getInt("error_code");
        return errorCode==0?true:false;
    }


    /**
     *  人脸注册 :将用户照片存入人脸库中
     */
    public Boolean faceRegister(String userId, String image) {
        // 人脸注册
        JSONObject res = client.addUser(image, IMAGE_TYPE, groupId, userId, options);
        Integer errorCode = res.getInt("error_code");
        return errorCode == 0 ? true : false;
    }

    /**
     *  人脸更新 :更新人脸库中的用户照片
     */
    public Boolean faceUpdate(String userId, String image) {
        // 人脸更新
        JSONObject res = client.updateUser(image, IMAGE_TYPE, groupId, userId, options);
        Integer errorCode = res.getInt("error_code");
        return errorCode == 0 ? true : false;
    }

    /**
     * 人脸检测:判断上传图片中是否具有面部头像
     */
    public Boolean faceCheck(String image) {
        JSONObject res = client.detect(image, IMAGE_TYPE, options);
        if (res.has("error_code") && res.getInt("error_code") == 0) {
            JSONObject resultObject = res.getJSONObject("result");
            Integer faceNum = resultObject.getInt("face_num");
            return faceNum == 1?true:false;
        }else{
            return false;
        }
    }

    /**
     *  人脸查找:查找人脸库中最相似的人脸并返回数据
     *          处理:用户的匹配得分(score)大于80分,即可认为是同一个用户
     */
    public Long faceSearch(String image) {
        JSONObject res = client.search(image, IMAGE_TYPE, groupId, options);
        if (res.has("error_code") && res.getInt("error_code") == 0) {
            JSONObject result = res.getJSONObject("result");
            JSONArray userList = result.getJSONArray("user_list");
            if (userList.length() > 0) {
                JSONObject user = userList.getJSONObject(0);
                double score = user.getDouble("score");
                if(score > 80) {
                    return user.getLong("user_id");
                }
            }
        }
        return null;
    }

    /**
     * 获取用户人脸列表接口
     *
     * @param userId - 用户id(由数字、字母、下划线组成),长度限制128B
     * options - options列表:
     * @return JSONObject
     */
    public JSONObject faceGetlist(String userId) {
        JSONObject res = client.faceGetlist(userId, groupId, options);
        if (res.has("error_code") && res.getInt("error_code") == 0) {
            JSONObject result = res.getJSONObject("result");
            JSONArray userList = result.getJSONArray("face_list");
            return result;
        }
        return null;
    }

    /**
     * 获取用户列表接口
     *
     * options - options列表:
     *   start 默认值0,起始序号
     *   length 返回数量,默认值100,最大值1000
     * @return JSONObject
     */
    public List getGroupUsers() {
        JSONObject res = client.getGroupUsers(groupId, options);
        if (res.has("error_code") && res.getInt("error_code") == 0) {
            JSONObject result = res.getJSONObject("result");
            JSONArray userList = result.getJSONArray("user_id_list");
            return userList.toList();
        }
        return null;
    }

    public Boolean faceDelete(String userId) {
        JSONObject res = client.deleteUser(groupId, userId, options);
        if (res.has("error_code") && res.getInt("error_code") == 0) {
            return true;
        }
        return false;
    }
}

package com.example.demo.service.impl;



import cn.hutool.core.codec.Base64;
import com.example.demo.util.BaiduAiUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.File;

@Service
public class FaceLoginService {

    @Value("${qr.url}")
    private String url;

    @Autowired
    private BaiduAiUtil baiduAiUtil;
    
    // 判断用户是否注册了面部信息
    public Boolean faceExist(String userId){
        Boolean aBoolean=baiduAiUtil.faceExist(userId);
        return aBoolean;
    }

    /**
     *  人脸注册 :将用户照片存入人脸库中
     */
    public Boolean faceRegister(String userId, File file) {
        Boolean aBoolean = false;
        // 人脸注册
        String image= Base64.encode(file);
        try {
            baiduAiUtil.faceDelete(userId);
            aBoolean = baiduAiUtil.faceRegister(userId, image);
        } catch (Exception e) {

        }
        return aBoolean;
    }

    public Long loginByFace(File file) throws Exception {
        String imgBase64= Base64.encode(file);
		Long userId=baiduAiUtil.faceSearch(imgBase64);
        return userId;
    }
}

package com.example.demo.util;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.UUID;

public class ImageUtils {
	
	/**
	 * 上传图片到指定位置
	 * @param request
	 * @param picName 客户端文件的name
	 * @param picPath 文件上传的路径
	 * @return
	 */
	public static File uploadImg(HttpServletRequest request, String picName, String picPath) {
		String imgData = request.getParameter(picName);//获取客户端传输到服务器的图片
        String path = request.getServletContext().getRealPath("/"+picPath+"/");//获取指定的图片上传到服务器的路径
        String fileName = UUID.randomUUID().toString().replace("-", "")+".png";//给图片一个随机名称
        boolean flag;
        if (imgData != null) {
            flag = generateImage(imgData.substring(22), path, fileName);//上传图片
        }
		System.out.println("图片上传:,地址:"+path);
		return new File(path+"/"+fileName);
	}

    private static boolean generateImage(String imgStr, String filePath, String fileName) {
        try {
            if (imgStr == null) {
                return false;
            }
            Decoder decoder = Base64.getDecoder();
            byte[] b = decoder.decode(imgStr);
            File file = new File(filePath);
            if (!file.exists()) {
                file.mkdirs();
            }
            OutputStream out = new FileOutputStream(filePath+fileName);
            out.write(b);
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

}

package com.example.demo.controller;



import com.example.demo.service.impl.FaceLoginService;
import com.example.demo.util.BaiduAiUtil;
import com.example.demo.util.ImageUtils;
import com.example.demo.util.ResponseVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;

@Controller
@RequestMapping("/face")
public class FaceLoginController {


    @Autowired
    private FaceLoginService faceLoginService;

    @Resource
    private BaiduAiUtil baiduAiUtil;

    @RequestMapping("/")
    public String hello() {
        return "login";
    }

    /**
     * 人脸登录:根据落地页随机拍摄的面部头像进行登录
     *          根据拍摄的图片调用百度云AI进行检索查找
     */
    @RequestMapping("/login")
    @ResponseBody
    public String face(HttpServletRequest request)  throws Exception{
        File file = ImageUtils.uploadImg(request, "imgData", "upimg");
        Long userId= faceLoginService.loginByFace(file);
        return null;
    }

    @RequestMapping("/register")
    @ResponseBody
    public String register(HttpServletRequest request) throws Exception {
        File file = ImageUtils.uploadImg(request, "imgData", "upimg");
        faceLoginService.faceRegister("userId", file);
        return null;
    }

}

login接口只是获取到了人脸库能够匹配到的人脸用户id信息,匹配不到则为null,伪代码不涉及业务逻辑。

图片获取方式

可以使用文件上传的方式,也可以使用web端的拍摄功能。本例就用web端的摄像头获取人脸图片。

<div class="btn-group btn-group-justified" role="group" aria-label="...">
                                <div class="btn-group" role="group">
                                    <button type="button" class="btn btn-default" onclick="openMedia()">开启摄像头</button>
                                </div>
                                <div class="btn-group" role="group">
                                    <button type="button" class="btn btn-default" onclick="closeMedia()">关闭摄像头</button>
                                </div>
                                <div class="btn-group" role="group">
                                    <button type="button" class="btn btn-default" onclick="takePhoto('login')">人脸登录</button>
                                </div>
                            </div>

                            <table class="panel panel-default">
                                <div class="panel-heading">Face!</div>
                                <td class="panel-body">
                                    <video id="video" width="300px" height="300px" autoplay="autoplay"></video>
                                    <canvas id="canvas" width="500px" height="500px" style="display: none"></canvas>
                                </td>
                            </table>
                            <script>
                                let mediaStreamTrack=null; // 视频对象(全局)
                                let video ;
                                function openMedia() {
                                    let constraints = {
                                        video: { width: 500, height: 500 },
                                        audio: false
                                    };
                                    //获得video摄像头
                                    video = document.getElementById('video');
                                    let promise = navigator.mediaDevices.getUserMedia(constraints);
                                    promise.then((mediaStream) => {
                                        mediaStreamTrack=mediaStream.getVideoTracks()
                                        video.srcObject = mediaStream;
                                        video.play();
                                    });
                                }
                                // 拍照
                                function takePhoto(str) {
                                    //获得Canvas对象
                                    let video = document.getElementById('video');
                                    let canvas = document.getElementById('canvas');
                                    let ctx = canvas.getContext('2d');
                                    ctx.drawImage(video, 0, 0, 500, 500);
                                    // toDataURL  ---  可传入'image/png'---默认, 'image/jpeg'
                                    let img = document.getElementById('canvas').toDataURL();
                                    // 这里的img就是得到的图片
                                    document.getElementById('canvas').src=img;
                                    //上传
                                    var flagStr="登录";
                                    // alert(str);
                                    $.ajax({
                                        url:"face/login",
                                        type:"POST",
                                        data:{"imgData":img
                                        },
                                        dataType: "json",
                                        success: function (json) {
                                            if (json.status == 200) {
                                                var historyUrl = json.data || "/";
                                                window.location.href = "/";
                                            } else if(json.status == 500){
                                                alert(json.message);
                                            } else{
                                                $.alert.error(json.message);
                                                $("#img-kaptcha").attr("src", '/getKaptcha?time=' + new Date().getTime());
                                            }
                                        }
                                    });

                                }

                                // 关闭摄像头
                                function closeMedia() {
                                    let stream = document.getElementById('video').srcObject;
                                    let tracks = stream.getTracks();

                                    tracks.forEach(function(track) {
                                        track.stop();
                                    });

                                    document.getElementById('video').srcObject = null;
                                }


                                $("#modal").modal('show');
                                $(".btn-login").click(function () {
                                    $(".login-loading").removeClass("hide");
                                    $.ajax({
                                        type: "POST",
                                        url: "face/login",
                                        data: $("#login-form").serialize(),
                                        dataType: "json",
                                        success: function (json) {
                                            $(".login-loading").addClass("hide");
                                            if (json.status == 200) {
                                                var historyUrl = json.data || "/";
                                                window.location.href = historyUrl;
                                            }else{
                                                $.alert.error(json.message);
                                                $("#img-kaptcha").attr("src", '/getKaptcha?time=' + new Date().getTime());
                                            }
                                        }
                                    });
                                });
                                $("#img-kaptcha").click(function () {
                                    $(this).attr("src", '/getKaptcha?time=' + new Date().getTime());
                                });
                                document.onkeydown = function (event) {
                                    var e = event || window.event || arguments.callee.caller.arguments[0];
                                    if (e && e.keyCode == 13) {
                                        $(".btn-login").click();
                                    }
                                };
                            </script>
                        </section>
                    </div>
  • 2
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值