基于node.js 实现百度ai人脸检测功能(api)

很有幸和老师同学们一起尝试学习百度ai的相关技术文档,自己做了一个很ez的人脸检测的小网页,和大家分享一下。

1.首先根据技术文档中的要求我们要获取access_token

这个我们只需要去注册自己的百度智能云的id账号,然后进入人脸识别页面页面,创建自己的应用,就可以获取到自己的API Key 以及Secret Key,拿到这个就可以去根据实例代码获取我们要的access_token了。

示例图如下:

nodejs使用axios nodejs ai_nodejs


根据百度ai技术文档提供的获取access_token的方法,可以获取到如下相关信息。

注意这是一个node的项目,相关模块需要用npm/cnpm安装,我想有node基础的同学就不用我阐述了。

官方获取access_token代码如下:

var https = require('https');
var qs = require('querystring');

const param = qs.stringify({
    'grant_type': 'client_credentials',
    'client_id': 'xCRoucNpcqBSL3Ssvyz9003z',
    'client_secret': 'wTxCPkMOnNZmat4PxWMgu8wU2QA8ZvGK'
});

https.get({
        hostname: 'aip.baidubce.com',
        path: '/oauth/2.0/token?' + param,
        agent: false
    },
    function (res) {
        // 在标准输出中查看运行结果
        res.pipe(process.stdout);
    }
);

注意:client_id 和 client_secert 分别填入你获取到的API Key 以及Secret Key。这样运行这个js文件, 用node命令运行,dos返回结果

/*{
    "refresh_token": "25.229e474f1ddaa3dd8bf615a0640c1db5.315360000.1886430622.282335-17511300",
    "expires_in": 2592000,
    "session_key": "9mzdWrktAR59shMTTbnfWJ2QNQo6NqrQQiSZlE94z70aI5ttomvuXYJVIPzSXw2n3cMf7hgoug5m4hhhYoeIUTlDmx+byA==",
    "access_token": "24.ae8755d49cf860037da7cb9f4868af07.2592000.1573662622.282335-17511300",
    "scope": "vis-ocr_ocr brain_ocr_idcard public brain_all_scope vis-faceverify_faceverify_h5-face-liveness vis-faceverify_FACE_V3 vis-faceverify_idl_face_merge brain_cvpaas-app-scope wise_adapt lebo_resource_base lightservice_public hetu_basic lightcms_map_poi kaidian_kaidian ApsMisTest_Test\u6743\u9650 vis-classify_flower lpq_\u5f00\u653e cop_helloScope ApsMis_fangdi_permission smartapp_snsapi_base iop_autocar oauth_tp_app smartapp_smart_game_openapi oauth_sessionkey smartapp_swanid_verify smartapp_opensource_openapi smartapp_opensource_recapi fake_face_detect_\u5f00\u653eScope",
    "session_secret": "c66f9aa948dc1c44b542d8798626ad6d"
}
*/

这里获取到的"access_token"就是我们要的数据

2.然后请求官方api,人脸识别的接口,这个会在你创建的应用下面有,分为v2和v3版本。

示例图如下:

nodejs使用axios nodejs ai_百度ai_02


如图可以看到人脸识别接口的api,以及接口是v3

然后完善我们后台的请求接口 /face

let express = require('express');
let https = require('https');
let request = require('request');
var router = express.Router();


//人脸识别接口
var token = "24.ae8755d49cf860037da7cb9f4868af07.2592000.1573662622.282335-17511300";

//url  林更新
var str = 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1219144778,2690834063&fm=26&gp=0.jpg';

router.post('/', (req, res) => {
    let options = {
        host: 'aip.baidubce.com',
        path: '/rest/2.0/face/v3/detect?access_token="' + token + '"',
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        }
    };

    let contents = JSON.stringify({     
       // url  图片类型
        image: str,
        image_type: "URL",
        "face_field": 'age,beauty,expression,face_shape,gender,glasses,race',
        //这里根据文档填入你想要获取到的参数
    });

    let req_baiduai = https.request(options, function (res_baiduai) {
        res_baiduai.setEncoding('utf8');
        res_baiduai.on('data', function (chunk) {
            res.send(chunk)
            var testResult = JSON.parse(chunk);
            console.log(chunk)
            res.end();
        })
    });
    req_baiduai.write(contents);
    req_baiduai.end();
});
module.exports = router;

注意: 如果要使用BASE64 图片类型

需要修改上述代码:
 var fs = require(‘fs’);
 var image = fs.readFileSync(’./ab.png’).toString(‘base64’);
 添加fs模块获取你要测试的本地图片并且转换为base64格式修改body请求体
 //base 64 图片类型
 image: image,
 image_type: “BASE64”,

3.通过前端获取到我们的后台接口/face返回的请求百度的数据
其中数据是通过ajax获取到的,并且通过js全局变量返回到全局环境以便于之后的渲染操作。

$.ajax({
        //几个参数需要注意一下
        type: "post", //方法类型
        // dataType: "json", //预期服务器返回的数据类型
        url: "http://localhost:2019/face", // url
        // data: $('#form1').serialize(),
        success: function (res) {
            {

                console.log(res); //打印服务端返回的数据(调试用);
                a += res;
                alert("提交成功!!!");
                return a;
            }
        },
        async: false,
        error: function () {
            alert("提交异常!");
        },
    });

4.布局前端页面

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title></title>
    <link rel="icon" href="../images/bg.jpg" type="images/x-ico" />
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    <script src="./js/vue.js"></script>
</head>
<style>
    * {
        margin: 0;
        padding: 0
    }

    html,
    body {
        width: 100%;
        height: 100%;
        background-image: url(../images/007.jpg);
        background-size: cover;
        overflow-y: hidden;
    }

    video {
        position: absolute;
        left: 100px;
        border: 10px solid white;
    }

    canvas {
        position: absolute;
        left: 150px;
        bottom: -20px;
    }

    button {
        position: absolute;
        width: 100px;
        height: 30px;
        top: 330px;
        left: 260px;
    }

    .result {
        position: absolute;
        width: 370px;
        height: 500px;
        right: 200px;
        top: 30px;
        /* border: 5px solid white; */
        text-align: center;
        padding: 20px;
        color: white;
        /* background: black; */
    }

    p {
        text-align: left;
        font-size: 20px;
        font-weight: 600;
        color: white;
        line-height: 30px;
    }
</style>

<body>
    <video id="video" width="400" height="300" autoplay></video>
    <button id="snap">Snap Photo</button>
    <canvas id="canvas" width="400" height="300"></canvas>

    <div class="result">
        <h1>人脸属性</h1>
        <p>"face_num":{{ msg0 }}</p>
        <p>"face_token":{{ msg1 }}</p>
        <p>"face_probability":{{ msg2 }}</p>
        <p>"age":{{ msg3 }}</p>
        <p>"beauty":{{ msg4 }}</p>
        <p>"expressiton":{{ msg5 }}</p>
        <p>"face_shape":{{ msg6 }}</p>
        <p>"gender":{{ msg7 }}</p>
        <p>"glasses":{{ msg8 }}</p>
        <p>"race":{{ msg9 }}</p>
    </div>
</body>
<script type="text/javascript">
    var aVideo = document.getElementById('video');
    var aCanvas = document.getElementById('canvas');
    var ctx = aCanvas.getContext('2d');

    navigator.getUserMedia = navigator.getUserMedia ||
        navigator.webkitGetUserMedia ||
        navigator.mozGetUserMedia ||
        navigator.msGetUserMedia; //获取媒体对象(这里指摄像头)
    navigator.getUserMedia({
        video: true
    }, gotStream, noStream); //参数1获取用户打开权限;参数二是一个回调函数,自动传入视屏流,成功后调用,并传一个视频流对象,参数三打开失败后调用,传错误信息

    function gotStream(stream) {

        // video.src = URL.createObjectURL(stream); // 老写法
        aVideo.srcObject = stream;

        aVideo.onerror = function () {
            stream.stop();
        };
        stream.onended = noStream;
        aVideo.onloadedmetadata = function () {
            // alert('摄像头成功打开!');
        };
    }

    function noStream(err) {
        alert(err);
    }

    document.getElementById("snap").addEventListener("click", function () {
        ctx.drawImage(aVideo, 0, 0, 320, 240); //将获取视频绘制在画布上
    });

    //cancas 保存图片
    


    var a = "";
    $.ajax({
        //几个参数需要注意一下
        type: "post", //方法类型
        // dataType: "json", //预期服务器返回的数据类型
        url: "http://localhost:2019/face", // url
        // data: $('#form1').serialize(),
        success: function (res) {
            {

                console.log(res); //打印服务端返回的数据(调试用);
                a += res;
                alert("提交成功!!!");
                return a;
            }
        },
        async: false,
        error: function () {
            alert("提交异常!");
        },
    });
    var testResult = JSON.parse(a);
    // var datalist = JSON.parse()

    var vm = new Vue({

        el: '.result', // 表示 我们 new的这个实例要去控制页面上的哪个区域
        data: { //data中存放的是el中要用到的数据
            msg0: testResult.result.face_num,
            msg1: testResult.result.face_list[0].face_token,
            msg2: testResult.result.face_list[0].face_probability,
            msg3: testResult.result.face_list[0].age,
            msg4: testResult.result.face_list[0].beauty,
            msg5: testResult.result.face_list[0].expression,
            msg6: testResult.result.face_list[0].face_shape,
            msg7: testResult.result.face_list[0].gender,
            msg8: testResult.result.face_list[0].glasses,
            msg9: testResult.result.face_list[0].race,


            //通过vue提供的指令就可以简单的把数据渲染到页面上,不提倡操作dom
        }
    });
</script>
<script>



</script>

</html>

其中数据是通过vue渲染上去的,可能拿数据比较粗鲁,但是因为时间原因,嘻嘻嘻,希望大家理解。

最后的效果如下:

nodejs使用axios nodejs ai_nodejs_03


测试

如果你使用的图片是url形式,只需要在网上找一些明星照片然后填入url地址就可以,如果你使用base64格式图片,可以在摄像头开启之后拍摄一张图片,(我是用canvas画布将拍照效果保存页面上,你可以直接右键保存到你的项目的文件夹下)然后再次刷新页面就会出现效果。