【快速上手系列】使用idea调百度AI接口实现人脸识别功能

news2025/7/27 4:00:38

【快速上手系列】使用idea调百度AI接口实现人脸识别功能

一、人脸检测

步骤

1、百度AI开放平台

登录后点击控制台

请添加图片描述

点击公有云服务——应用列表——点击创建应用

请添加图片描述

填写一下信息然后创建

请添加图片描述

然后回到概览——领取免费资源(如果账号没领取过的话)

请添加图片描述

可以自选,不过嫌麻烦直接全选了也一样

请添加图片描述

然后回到概览——点击调用服务下的API文档

请添加图片描述

获取api

到API文档下滑,可以看到获取Access Token的工具类

请添加图片描述

再往下滑可以看到demo的示例代码(懒的搞下面有代码)

请添加图片描述

获取sdk

点击概览下HTTP SDK

请添加图片描述

调转后可以看到所有的接口需要的各平台sdk,是离线的jar包
请添加图片描述

2、idea创建demo

idea新建一个maven项目

maven依赖

pom.xml

<dependency>
    <groupId>com.baidu.aip</groupId>
    <artifactId>java-sdk</artifactId>
    <version>4.6.0</version>
</dependency>
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20160810</version>
</dependency>
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.9.0</version>
</dependency>
项目结构

请添加图片描述

Base64Util:Base64 工具类

FileUtil:文件读取工具类

GetAccessToken:获取token类

GsonUtils:Json工具类.

HttpUtil:http 工具类

tips:不是哪个项目都会用到,看情况,懒的话全扔里就行

五个工具类代码

Base64Util.java

package utils;

/**
 * Base64 工具类
 */
public class Base64Util {
    private static final char last2byte = (char) Integer.parseInt("00000011", 2);
    private static final char last4byte = (char) Integer.parseInt("00001111", 2);
    private static final char last6byte = (char) Integer.parseInt("00111111", 2);
    private static final char lead6byte = (char) Integer.parseInt("11111100", 2);
    private static final char lead4byte = (char) Integer.parseInt("11110000", 2);
    private static final char lead2byte = (char) Integer.parseInt("11000000", 2);
    private static final char[] encodeTable = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};

    public Base64Util() {
    }

    public static String encode(byte[] from) {
        StringBuilder to = new StringBuilder((int) ((double) from.length * 1.34D) + 3);
        int num = 0;
        char currentByte = 0;

        int i;
        for (i = 0; i < from.length; ++i) {
            for (num %= 8; num < 8; num += 6) {
                switch (num) {
                    case 0:
                        currentByte = (char) (from[i] & lead6byte);
                        currentByte = (char) (currentByte >>> 2);
                    case 1:
                    case 3:
                    case 5:
                    default:
                        break;
                    case 2:
                        currentByte = (char) (from[i] & last6byte);
                        break;
                    case 4:
                        currentByte = (char) (from[i] & last4byte);
                        currentByte = (char) (currentByte << 2);
                        if (i + 1 < from.length) {
                            currentByte = (char) (currentByte | (from[i + 1] & lead2byte) >>> 6);
                        }
                        break;
                    case 6:
                        currentByte = (char) (from[i] & last2byte);
                        currentByte = (char) (currentByte << 4);
                        if (i + 1 < from.length) {
                            currentByte = (char) (currentByte | (from[i + 1] & lead4byte) >>> 4);
                        }
                }

                to.append(encodeTable[currentByte]);
            }
        }

        if (to.length() % 4 != 0) {
            for (i = 4 - to.length() % 4; i > 0; --i) {
                to.append("=");
            }
        }

        return to.toString();
    }
}

FileUtil.java

package utils;

import java.io.*;

/**
 * 文件读取工具类
 */
public class FileUtil {

    /**
     * 读取文件内容,作为字符串返回
     */
    public static String readFileAsString(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException(filePath);
        } 

        if (file.length() > 1024 * 1024 * 1024) {
            throw new IOException("File is too large");
        } 

        StringBuilder sb = new StringBuilder((int) (file.length()));
        // 创建字节输入流  
        FileInputStream fis = new FileInputStream(filePath);  
        // 创建一个长度为10240的Buffer
        byte[] bbuf = new byte[10240];  
        // 用于保存实际读取的字节数  
        int hasRead = 0;  
        while ( (hasRead = fis.read(bbuf)) > 0 ) {  
            sb.append(new String(bbuf, 0, hasRead));  
        }  
        fis.close();  
        return sb.toString();
    }

    /**
     * 根据文件路径读取byte[] 数组
     */
    public static byte[] readFileByBytes(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException(filePath);
        } else {
            ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length());
            BufferedInputStream in = null;

            try {
                in = new BufferedInputStream(new FileInputStream(file));
                short bufSize = 1024;
                byte[] buffer = new byte[bufSize];
                int len1;
                while (-1 != (len1 = in.read(buffer, 0, bufSize))) {
                    bos.write(buffer, 0, len1);
                }

                byte[] var7 = bos.toByteArray();
                return var7;
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException var14) {
                    var14.printStackTrace();
                }

                bos.close();
            }
        }
    }
}

GetAccessToken.java(需要输入自己应用的API Key和Secret Key哦)

package utils;

import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

/**
 * 获取token类
 */
public class GetAccessToken {

    /**
     * 获取权限token
     * @return 返回示例:
     * {
     * "access_token": "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567",
     * "expires_in": 2592000
     * }
     */
    public static String getAuth() {
        // 官网获取的 API Key 更新为你注册的
        String clientId = "XXXXXXXXXXXXXXXXXXXXXXX";
        // 官网获取的 Secret Key 更新为你注册的
        String clientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        return getAuth(clientId, clientSecret);
    }

    /**
     * 获取API访问token
     * 该token有一定的有效期,需要自行管理,当失效时需重新获取.
     * @param ak - 百度云官网获取的 API Key
     * @param sk - 百度云官网获取的 Secret Key
     * @return assess_token 示例:
     * "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567"
     */
    public static String getAuth(String ak, String sk) {
        // 获取token地址
        String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
        String getAccessTokenUrl = authHost
                // 1. grant_type为固定参数
                + "grant_type=client_credentials"
                // 2. 官网获取的 API Key
                + "&client_id=" + ak
                // 3. 官网获取的 Secret Key
                + "&client_secret=" + sk;
        try {
            URL realUrl = new URL(getAccessTokenUrl);
            // 打开和URL之间的连接
            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.err.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String result = "";
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            /**
             * 返回结果示例
             */
            System.err.println("result:" + result);
            JSONObject jsonObject = new JSONObject(result);
            String access_token = jsonObject.getString("access_token");
            return access_token;
        } catch (Exception e) {
            System.err.printf("获取token失败!");
            e.printStackTrace(System.err);
        }
        return null;
    }

}

GsonUtils.java

/*
 * Copyright (C) 2017 Baidu, Inc. All Rights Reserved.
 */
package utils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;

import java.lang.reflect.Type;

/**
 * Json工具类.
 */
public class GsonUtils {
    private static Gson gson = new GsonBuilder().create();

    public static String toJson(Object value) {
        return gson.toJson(value);
    }

    public static <T> T fromJson(String json, Class<T> classOfT) throws JsonParseException {
        return gson.fromJson(json, classOfT);
    }

    public static <T> T fromJson(String json, Type typeOfT) throws JsonParseException {
        return (T) gson.fromJson(json, typeOfT);
    }
}

HttpUtil.java

package utils;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

/**
 * http 工具类
 */
public class HttpUtil {

    public static String post(String requestUrl, String accessToken, String params)
            throws Exception {
        String contentType = "application/x-www-form-urlencoded";
        return HttpUtil.post(requestUrl, accessToken, contentType, params);
    }

    public static String post(String requestUrl, String accessToken, String contentType, String params)
            throws Exception {
        String encoding = "UTF-8";
        if (requestUrl.contains("nlp")) {
            encoding = "GBK";
        }
        return HttpUtil.post(requestUrl, accessToken, contentType, params, encoding);
    }

    public static String post(String requestUrl, String accessToken, String contentType, String params, String encoding)
            throws Exception {
        String url = requestUrl + "?access_token=" + accessToken;
        return HttpUtil.postGeneralUrl(url, contentType, params, encoding);
    }

    public static String postGeneralUrl(String generalUrl, String contentType, String params, String encoding)
            throws Exception {
        URL url = new URL(generalUrl);
        // 打开和URL之间的连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        // 设置通用的请求属性
        connection.setRequestProperty("Content-Type", contentType);
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setUseCaches(false);
        connection.setDoOutput(true);
        connection.setDoInput(true);

        // 得到请求的输出流对象
        DataOutputStream out = new DataOutputStream(connection.getOutputStream());
        out.write(params.getBytes(encoding));
        out.flush();
        out.close();

        // 建立实际的连接
        connection.connect();
        // 获取所有响应头字段
        Map<String, List<String>> headers = connection.getHeaderFields();
        // 遍历所有的响应头字段
        for (String key : headers.keySet()) {
            System.err.println(key + "--->" + headers.get(key));
        }
        // 定义 BufferedReader输入流来读取URL的响应
        BufferedReader in = null;
        in = new BufferedReader(
                new InputStreamReader(connection.getInputStream(), encoding));
        String result = "";
        String getLine;
        while ((getLine = in.readLine()) != null) {
            result += getLine;
        }
        in.close();
        System.err.println("result:" + result);
        return result;
    }
}
测试类

FaceDetect.java(写入路径然后运行就行)

import com.baidu.aip.util.Base64Util;
import utils.FileUtil;
import utils.GetAccessToken;
import utils.HttpUtil;
import utils.GsonUtils;
import java.util.*;

/**
 * 人脸检测与属性分析
 */
public class FaceDetect {

    /**
     * 重要提示代码中所需工具类
     * FileUtil,Base64Util,HttpUtil,GsonUtils请从
     * https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72
     * https://ai.baidu.com/file/C8D81F3301E24D2892968F09AE1AD6E2
     * https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3
     * https://ai.baidu.com/file/470B3ACCA3FE43788B5A963BF0B625F3
     * 下载
     */
    public static String faceDetect() {
        // 请求url
        String url = "https://aip.baidubce.com/rest/2.0/face/v3/detect";
        try {
            Map<String, Object> map = new HashMap<>();
            //这里需要将本地图片进行Base64编码
            byte[] bytes = FileUtil.readFileByBytes("e:\\11.jpg");
            String img = Base64Util.encode(bytes);
            map.put("image", img);
            map.put("face_field", "faceshape,facetype");
            //这里也要改成BASE64
            map.put("image_type", "BASE64");

            String param = GsonUtils.toJson(map);

            // 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。
            String accessToken = GetAccessToken.getAuth();;

            String result = HttpUtil.post(url, accessToken, "application/json", param);
            System.out.println(result);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        FaceDetect.faceDetect();
    }
}

测试结果:

请添加图片描述

Test.java(这个要输入AppID、 API Key 、Secret Key 和图片路径)

import com.baidu.aip.face.AipFace;
import org.apache.commons.codec.binary.Base64;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

public class Test {

    //设置AppID、API Key和Secret Key
    public static final String APP_ID = "XXXXXXXXXXXXXX";
    public static final String API_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXX";
    public static final String SECRET_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

    public static void main(String[] args) {
        String image = base64();
        String imageType = "BASE64";

        // 初始化一个AipFace
        AipFace client = new AipFace(APP_ID, API_KEY, SECRET_KEY);

        // 可选:设置网络连接参数
        client.setConnectionTimeoutInMillis(2000);
        client.setSocketTimeoutInMillis(60000);

        // 可选:设置代理服务器地址, http和socket二选一,或者均不设置
//        client.setHttpProxy("proxy_host", proxy_port);  // 设置http代理
//        client.setSocketProxy("proxy_host", proxy_port);  // 设置socket代理

        // 传入可选参数调用接口,根据需求自行设置
        HashMap<String, String> options = new HashMap<String, String>();
        options.put("face_field", "age,beauty,expression,face_shape,gender,glasses,race,eye_status,emotion,face_type");
//        options.put("max_face_num", "2");
//        options.put("face_type", "LIVE");
//        options.put("liveness_control", "LOW");

        JSONObject res = client.detect(image, imageType, options);
        if (res.getString("error_msg") != null && res.getString("error_msg").equals("SUCCESS")) {
            JSONArray faceList = res.getJSONObject("result").getJSONArray("face_list");
            JSONObject jsonObject = faceList.getJSONObject(0);

            System.out.println("年龄:" + jsonObject.getInt("age"));
            // 美丑打分,范围0-100,越大表示越美。
            System.out.println("美丑打分:" + jsonObject.getDouble("beauty"));
            // none:不笑;smile:微笑;laugh:大笑
            System.out.println("表情:" + jsonObject.getJSONObject("expression").getString("type"));
            // square: 正方形 triangle:三角形 oval: 椭圆 heart: 心形 round: 圆形
            System.out.println("脸型:" + jsonObject.getJSONObject("face_shape").getString("type"));
            // male:男性 female:女性
            System.out.println("性别:" + jsonObject.getJSONObject("gender").getString("type"));

            // yellow: 黄种人 white: 白种人 black:黑种人 arabs: 阿拉伯人
            System.out.println("人种:" + jsonObject.getJSONObject("race").getString("type"));

            // [0,1]取值,越接近0闭合的可能性越大
            System.out.println("右眼状态(睁开/闭合):" + jsonObject.getJSONObject("eye_status").getInt("right_eye"));
            System.out.println("左眼状态(睁开/闭合):" + jsonObject.getJSONObject("eye_status").getInt("left_eye"));
            System.out.println("人脸置信度,范围【0~1】:" + jsonObject.getInt("face_probability"));
            // none:无眼镜,common:普通眼镜,sun:墨镜
            System.out.println("是否带眼镜:" + jsonObject.getJSONObject("glasses").getString("type"));
            // angry:愤怒 disgust:厌恶 fear:恐惧 happy:高兴 sad:伤心 surprise:惊讶 neutral:无情绪
            System.out.println("情绪:" + jsonObject.getJSONObject("emotion").getString("type"));
            // human: 真实人脸 cartoon: 卡通人脸
            System.out.println("真实人脸/卡通人脸:" + jsonObject.getJSONObject("face_type").getString("type"));
            System.out.println("face_token:" + jsonObject.getString("face_token"));

        } else {
            System.out.println(res.toString());
        }
    }

    public static String base64() {
        //将图片文件转化为字节数组字符串,并对其进行Base64编码处理
        InputStream in = null;
        byte[] data = null;
        //读取图片字节数组
        try {
            in = new FileInputStream("e:\\11.jpg");
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new String(Base64.encodeBase64(data));
    }
}

测试结果:

请添加图片描述

二、人脸对比

步骤

1、百度开放平台

获取Java-SDK文档

在百度开放平台中选择技术文档

请添加图片描述

然后在技术文档选择SDK文档—Java-SDK—然后如图

请添加图片描述

下载Java-SDK的demo源码:

JAVA SDK下载地址:https://github.com/Baidu-AIP/java-sdk

demo的目录结构

请添加图片描述

需要添加的maven依赖

请添加图片描述

pom.xml(本例子好像并没有用到)

<dependency>
    <groupId>com.baidu.aip</groupId>
    <artifactId>java-sdk</artifactId>
    <version>${version}</version>
</dependency>

2、idea创建demo

首先创建一个springboot项目(maven啥的应该也可以,但是结构要自己搞😬)

然后文件我是粘过来的

项目结构如图

请添加图片描述

其中face包中的AipFace类是百度提供给我们的人脸识别相关接口的工具类,这是主要要用到的

请添加图片描述

然后可以准备两张图片来先测试一下

测试

新建一个测试类Test.java

分别将自己应用的 AppID 、 API Key 、 Secret Key和准备的两张图片路径放进去改一下运行即可

package com.r.demo3;

import com.r.demo3.face.AipFace;
import com.r.demo3.face.MatchRequest;
import org.json.JSONObject;
import sun.misc.BASE64Encoder;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author Tuerlechat,
 * @Date 2022/11/9
 */
public class Test {
    public static final String APP_ID = "---你的APPID---";
    public static final String API_KEY = "---你的APIKEY---";
    public static final String SECRET_KEY = "---你的SECRETKEY---";

    public static void main(String[] args) {
        AipFace aipFace = new AipFace(APP_ID, API_KEY, SECRET_KEY);
        //准备的两张图片
        String img1="e:\\测试\\1.jpg";
        String img2="e:\\测试\\2.jpg";
        //两张不一样的图片
        String getImageStr1 = GetImageStr(img1);
        String getImageStr2 = GetImageStr(img2);

//        String getImageStr3 = GetImageStr(img1);

        List<MatchRequest> input = new ArrayList<>();
        MatchRequest mr1 = new MatchRequest(getImageStr1, "BASE64");
        MatchRequest mr2 = new MatchRequest(getImageStr2, "BASE64");
//        MatchRequest mr2 = new MatchRequest(getImageStr3, "BASE64");
        input.add(mr1);
        input.add(mr2);
        JSONObject match = aipFace.match(input);
        System.out.println(match);
    }

    public static String GetImageStr(String imgFile) {//将图片文件转化为字节数组字符串,并对其进行Base64编码处理
        InputStream in = null;
        byte[] data = null;
        //读取图片字节数组
        try {
            in = new FileInputStream(imgFile);
            data = new byte[in.available()];
            in.read(data);
            in.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
        //对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);//返回Base64编码过的字节数组字符串
    }

}

我用了两张自己的照片,运行可以看到结果显示

请添加图片描述

请求成功然后相似度99点多😂

然后可以建一个controller来访问前端页面验证登录测试

人脸登录测试

controller层

这里还是需要你的自己应用的 AppID 、 API Key 、 Secret Key,这里还有一张图片路径是一会用于验证登录

FaceController.java

package com.r.demo3.controller;

import com.r.demo3.face.AipFace;
import com.r.demo3.face.MatchRequest;
import org.json.JSONObject;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import sun.misc.BASE64Encoder;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author Tuerlechat,
 * @Date 2022/11/9
 */
@RestController
@RequestMapping("/Face")
public class FaceController {
    public static final String APP_ID = "---你的APPID---";
    public static final String API_KEY = "---你的APIKEY---";
    public static final String SECRET_KEY = "---你的SECRETKEY---";

    @PostMapping( "/test")
    public String Test(@RequestParam("image") String image) {
        String substring = image.substring("data:image/jpeg;base64,".length());
        AipFace aipFace = new AipFace(APP_ID, API_KEY, SECRET_KEY);
        String img1="e:\\Shardddnshot.jpg";
        //两张不一样的图片
        String getImageStr1 = GetImageStr(img1);
        List<MatchRequest> input = new ArrayList<>();
        MatchRequest mr1 = new MatchRequest(getImageStr1, "BASE64");
        MatchRequest mr2 = new MatchRequest(substring, "BASE64");

        input.add(mr1);
        input.add(mr2);
        JSONObject match = aipFace.match(input);
        System.out.println(match);
        return match.toString();
    }

    public static String GetImageStr(String imgFile) {//将图片文件转化为字节数组字符串,并对其进行Base64编码处理
        InputStream in = null;
        byte[] data = null;
        //读取图片字节数组
        try {
            in = new FileInputStream(imgFile);
            data = new byte[in.available()];
            in.read(data);
            in.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
        //对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);//返回Base64编码过的字节数组字符串
    }
}

前端页面

photo.html(记得改一下页面中的jquery路径)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8"/>
    <title>人脸验证登录</title>
    <!-- 样式部分可以忽略 -->
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        div {
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .btn {
            width: 100px;
            height: 50px;
            border-radius: 10px;
            background: #ff9900;
            line-height: 50px;
            text-align: center;
            color: #fff;
            box-shadow: 0 0 10px #999;
        }

        #video {
            width: 300px;
            height: 300px;
            border: 5px solid #000;
            border-radius: 10px;
            margin-left: 5px;
        }

        #canvas {
            width: 300px;
            height: 300px;
            border: 5px solid #000;
            border-radius: 10px;
            margin-left: 5px;
        }
    </style>
</head>
<script src="js/jquery-3.6.0.js" type="text/javascript" charset="utf-8"></script>

<body>
<div>
    <div id="play" class="btn">开始摄像</div>
    <div id="take" class="btn">拍照</div>
    <div id="sub_btn" class="btn">登录</div>
    <video id="video"></video>
    <!-- 尽量在canvas标签上设置宽高 -->
    <canvas id="canvas" width="300px" height="300px"></canvas>

</div>
<script>
    $(function () {
        // 开启摄像
        document.getElementById('play').onclick = () => {
            let constraints = {
                // video属性设置
                video: {
                    width: 300,
                    height: 300
                },
                // audio属性设置
                audio: false
            }
            navigator.mediaDevices.getUserMedia(constraints)
                .then(mediaStream => {
                    // 成功返回promise对象,接收一个mediaStream参数与video标签进行对接
                    document.getElementById('video').srcObject = mediaStream
                    document.getElementById('video').play()
                })
            // 失败就失败了
        }
        // 拍照、canvas绘制
        document.getElementById('take').onclick = () => {
            let ctx = document.getElementById("canvas").getContext('2d')
            ctx.drawImage(document.getElementById("video"), 0, 0, 300, 300)
        }

        $("body").on("click", "#sub_btn", function () {
            var imgdata = document.getElementById("canvas").toDataURL("image/jpeg");
            console.log(imgdata)
            $.ajax({
                url:"/Face/test",
                type:"post",
                async: true,
                dataType:"json",
                contentType : "application/x-www-form-urlencoded; charset=utf-8",
                data:{
                    image:imgdata
                },
                success:function (res) {
                    if (res.result.score>70)
                        alert("登录成功")
                    else  alert("登录失败")
                }
            })

        });


    })
</script>
</body>

</html>

然后启动springboot,访问photo.html

进来之后是这样的:

请添加图片描述

tips:如果没输错东西但是点击开始摄像却没摄像头的话,在url地址栏右侧那个小摄像机打开开启电脑相机的权限,像这样

请添加图片描述

不方便露脸,所以用了两张jisoo和rose的照片来测试一下🤓

请添加图片描述

可以看到是能够成功登录的,说明人脸验证成功

换一张试试

请添加图片描述

可以看到登录失败,说明人脸验证是生效的

这样就搞好啦😁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/16743.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[Java] [Spring boot] Mybatis generator 生成Mapper.xml无效的问题

报错&#xff1a;org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): 百度出来的解决方案&#xff1a; 1&#xff1a;Mapper.xml中的namespace不对应和mapper接口不对应 2&#xff1a;Mapper.xml中的方法(即id)和mapper接口中的方法名字不同或…

使用 nexus 作为 npm 私服

背景: 之前公司内部是使用的 verdaccio 作为私有前端 npm 仓库的工具的, 由于最近安装包时总是遇到问题, 发包 和 安装都比较慢, 不太确定具体是什么问题 几经解决还是没能够解决掉, 索性换一个工具试试, 公司后端的 maven 库私服是使用的 nexus, 找资料时发现 nexus 也是可…

C++,STL,,vector容器

文章目录一、vector介绍1.vector对象构造2.vector的赋值3.vector的大小4.vector末尾的添加移除操作5.vector的数据存取6.vector的插入7.vector的删除8.vector迭代器一、vector介绍 vector相当于顺序表 vector是将元素置于一个动态数组中加以管理的容器。 vector可以随机存取元…

天元宠物上市首日破发:市值蒸发约5亿元,薛元潮兄妹为实控人

11月18日&#xff0c;杭州天元宠物用品股份有限公司&#xff08;下称“天元宠物”&#xff0c;SZ:301335&#xff09;在深圳证券交易所创业板上市。本次上市&#xff0c;天元宠物的发行价格为49.98元/股&#xff0c;发行数量为2250万股&#xff0c;募资总额约为11.25亿元&#…

华玉通软发布“云雀”执行管理中间件,为智能驾驶关键应用提供确定性执行保障

11月17日&#xff0c;华玉通软&#xff08;下称“华玉”&#xff09;宣布正式发布“云雀”执行管理中间件&#xff08;LARK EM Execution Management&#xff09;。 这是继“雨燕”通信中间件&#xff08;SWIFT DDS&#xff09;后&#xff0c;华玉的又一款完全自主研发的智能驾…

[iOS]分析Mach-O文件

一、Mach-O文件介绍 我们拿到IPA文件后&#xff0c;解压后就能拿到一个与APP同名的可执行文件。 Mach-O为Mach Object文件格式的缩写&#xff0c;它是一种用于可执行文件&#xff0c;目标代码&#xff0c;动态库&#xff0c;内核转储的文件格式。 每个Mach-O文件包括一个Mach-…

Design A NearBy Friends

title: Notes of System Design No.09 — Design a Uber backend description: Design a PasteBin ’ date: 2022-05-13 18:01:58 tags: 系统设计 categories: 系统设计 00. What is Newarby Friends? 01.Functional Requirement 02. Non-Functional Requirement 03. Assump…

Java新特性(2):Java 10以后

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 虽然到目前为止Java的版本更新还没有什么惊天动地的改变&#xff0c;但总是会冒出一些有趣的小玩意。前面列举了Java9和Java10的一些特色&#xff0c;现在接着来…

shell修改永久性别名,压缩与解压缩(zip gzip bzip2)文件上传预下载(sftp)

命令别名&#xff08;永久有效&#xff09; 敲重点&#xff08;写入文件&#xff09;&#xff08;1&#xff09;仅对root有效&#xff0c;写一个命令命为hello,实现的功能为每输入一次hello命令&#xff0c;就有hello&#xff0c;everyone写入文件/file.txt中。 root用户…

[UE][C++]Assimp库安装编译,UE_Assimp插件安装使用,各种三维格式转换

[UE][C]Assimp库安装编译&#xff0c;UE_Assimp插件安装使用&#xff0c;各种三维格式转换写在前面1.作者碎碎念2.结果1.需要准备的软件2.Assimp库编译步骤3.UE_Assimp插件的安装4.UE_Assimp插件样例使用5.Assimp库各种三维格式转换小程序写在前面 1.作者碎碎念 &#xff08;…

ElasticSearch 拼音插件elasticsearch-analysis-pinyin + IK 分词器

ElasticSearch kibana 部署略 创建索引 PUT /nba_20220101 {"mappings": {"properties": {"age": {"type": "integer"},"birthDay": {"type": "date"},"birthDayStr": {"t…

软件方面的文档标准GB/T

在文档标准方面&#xff0c;主要有《软件文档管理指南》&#xff08;GB/T 16680-1996&#xff09;、《计算机软件产品开发文件编制指南》&#xff08;GB/T 8567-2006&#xff09;和《计算机软件需求说明编制指南》&#xff08;GB/T 9385-2008&#xff09;等三个标准。 1. GB/T…

C语言源代码系列-管理系统之学生信息管理系统

往期文章分享点击跳转>《导航贴》- Unity手册&#xff0c;系统实战学习点击跳转>《导航贴》- Android手册&#xff0c;重温移动开发 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过…

竞赛开源项目汇总

1、Kaggle Titanic 一个Kaggle竞赛的案例&#xff0c;演示基本的数据转换、分析和可视化技术 https://github.com/agconti/kaggle-titanic 2、Humpback Whale Identification 1st https://github.com/earhian/Humpback-Whale-Identification-1st- 3、Data Science Competi…

【附源码】计算机毕业设计JAVA砂石矿山管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis Maven Vue 等等组成&#xff0c;B/…

无代码开发工具突破数据“孤岛“,让数据“动”起来

在信息化的发展过程中&#xff0c;每个独立运作的企业和机构都会使用2-3种以上的软件&#xff0c;而在某些比较成熟的公司&#xff0c;其软件产品的数量就更加惊人了&#xff0c;一个中等规模的公司可以拥有数百套软件系统来支持公司的正常运转。 许多公司的CIO或CTO&#xff0…

智能漏电断路器主要有哪些功能?

安科瑞 华楠 ASCB1 系列智能微型断路器是安科瑞电气股份有限公司 全新推出的智慧用电产品&#xff0c;产品由智能微型断路器与智 能网关两部分组成&#xff0c;可用于对用电线路的关键电气因 素&#xff0c;如电压、电流、功率、温度、漏电、能耗等进行实 时监测&#xff0c;具…

DOX-TF/Ce6/IgG 转铁蛋白/光敏剂/单抗IgG修饰阿霉素/阿霉素白蛋白纳米粒的制备

今天要分享的科研知识是DOX-TF/Ce6/IgG 转铁蛋白/光敏剂/单抗IgG修饰阿霉素/阿霉素白蛋白纳米粒&#xff0c;下面和小编一起来看&#xff01; DOX-IgG 单抗IgG偶联阿霉素的制备&#xff1a; 设计了一种叶酸-聚乙二醇-免疫球蛋白G-阿霉素(FA-PEG-IgG-DOX)的四元靶向给药系统.其…

石子合并系列问题

石子合并 石子合并问题在网上有三个版本&#xff1a; AcWing 282. 石子合并 设有 N 堆石子排成一排&#xff0c;其编号为 1&#xff0c;2&#xff0c;3&#xff0c;…&#xff0c;N。 每堆石子有一定的质量&#xff0c;可以用一个整数来描述&#xff0c;现在要将这 N 堆石子合…

Android 编译C++

Android 编译C项目前言正文一、基本知识① 要做什么&#xff1f;② JNI是什么&#xff1f;③ NDK是什么&#xff1f;二、配置NDK三、创建新工程① 工程目录说明② 分析cpp文件③ JNI数据类型四、现有工程使用C① 创建C文件② 创建CMake③ 使用C五、源码前言 在开发过程中&#…