百度AI 人臉識別 v3 node版

2018-04-27 人臉接口V3版本發佈 新增人臉庫管理等功能


本篇文章介紹瞭如何使用 nodejs 調用V3版本的人臉識別api


2018-05-05

nodejs 後臺

var https = require('https')
var qs = require('querystring')
//用express搭建的服務器
var express = require('express')
var app = express()
var fs = require('fs')
var bodyParser = require('body-parser')

/*
 每次啓動時都會 請求 /access 接口,從而獲取新的access_token,或者可以 持久化數據,保存在json文件裏,
 每隔一個月更新一次,因爲每隔一個月給的access_token都會不一樣
*/
var access_token = ''

const param = qs.stringify({
    'grant_type': 'client_credentials',
    'client_id': '你的 API key', 
    'client_secret': '你的 Secret Key' 
})

//這是我要對比的圖片,寫的時候有一個問題就是png的圖片和jpg的圖片不能對比,所以我都替換成png圖片了
var bitmap = fs.readFileSync('./images/my03.png')
//圖片轉爲 base64格式
var base64str1 = new Buffer(bitmap).toString('base64')

//bodyParser.urlencoded 限制了提交的大小不超過 50mb
app.use(bodyParser.urlencoded({limit: '50mb', extended: true }))

//我的html,js放在faceid文件夾下
app.use(express.static('../faceid'))

app.post('/access', function (req, res) {
    https.get(
        {
            hostname: 'aip.baidubce.com',
            path: '/oauth/2.0/token?' + param,
            agent: false
        },
        function (res) {
            res.setEncoding('utf8')
            res.on('data',function (data) {
            //取得access_token
                access_token = JSON.parse(data).access_token
            })
        }
    )
})

//這是 html界面 post請求 的judge 
app.post('/judge', function (req, res) {
    let  options = {
        host: 'aip.baidubce.com',
        path: '/rest/2.0/face/v3/match?access_token="'+access_token+'"',
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        }
    }
    //這裏還有很多參數,我都沒寫,具體的看官網
    /*
        從html界面傳回來的數據req.body.img,然後用正則來格式化,
        replace(/\s/g, "+")這個是把任何的Unicode空白符轉化爲 +
        replace(/^data:image\/\w+\Wbase64,/, "") 再把字符串開頭的data:image/png;base64 刪除
        ^ 匹配字符串的開頭,
        \/匹配/
        \w+ 匹配任何ASCII字符組成的單詞 
        \W  匹配任何非ASCII字符

    */
    let contents = JSON.stringify([
        {
            image: base64str1,
            image_type: "BASE64",
        }, {
            image: req.body.img.replace(/\s/g, "+").replace(/^data:image\/\w+\Wbase64,/, ""),
            image_type: "BASE64",
        }
    ])

    let req_baidu = https.request(options, function (res_baidu) {
        res_baidu.setEncoding('utf8')
        res_baidu.on('data', function (chunk) {
            //百度返回來的數據,有得分,直接發給html,在html中處理
            res.send(chunk)
        })

    })
    req_baidu.write(contents)
    req_baidu.end()

})
//服務在3302端口
var server = app.listen(3302, function () {
    console.log('listening at http://%s','localhost:3302');
})

接下來是 html 代碼

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="best" content="Best">
    <title>人臉識別</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        html, body {
            height: 100%;
            background: #f9f9f9;
        }

        body {
            display: flex;
            /*彈性佈局,用來爲盒狀模型提供最大的靈活性。任何一個容器都可以指定爲Flex佈局。
                       子元素的float、clear和vertical-align屬性將失效。http://blog.csdn.net/u011300580/article/details/56011564*/
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }

        .veriface {
            width: 800px;
            height: 500px;
            background-color: #FFFFFF;
            display: flex;
            flex-direction: column;
            justify-content: space-around;
            align-items: center;
        }

        .veriface .capture {
            display: block;
            width: 760px;
            height: 360px;
            background-color: #222222;
        }

        .veriface .control {
            display: flex;
            flex-direction: row;
            justify-content: space-around;
            align-items: center;
            width: 100%;
            height: 70px;
        }

        .veriface .control span {
            width: 100px;
            height: 45px;
            background: #F9F9F9;
            text-align: center;
            line-height: 45px;
            color: #222222;
            font-size: 12px;
            border-radius: 8px;
            box-shadow: 0 0 4px #cccccc;
            user-select: none;
            cursor: pointer;
            transition: 1s;
        }

        .veriface .control span:hover {
            background-color: #e6e6e6;
        }

        .veriface h3.notice {
            color: #336688;
        }
        .draw_img{
            position: fixed;
            bottom: 0px;
            left: 0px;
        }
    </style>
</head>
<body>
<canvas class="draw_img" width="300" height="200"></canvas>
<div class="veriface" style="margin-top: 3px">
    <video class="capture" width="760" height="360" src=""></video>
    <h3 class="notice">把臉放過來</h3>
    <div class="control">
        <span class="open">開啓攝像頭</span>
        <span class="recognition">人臉識別</span>
        <span class="close">關閉攝像頭</span>
    </div>
</div>
<script>
    /*
          從前臺到後臺的人臉識別
            1.開啓攝像頭
                1)window.navigator
            2.同步到video的src
                對象=> window.URL =>blob
                1)解析視頻流爲blob 添加到 src
            3.canvas創建視頻片段照片
            4.
    */

    var open = document.querySelector('.open');//獲取open按鈕
    var capture = document.querySelector('.capture'); // 獲取video標籤
    var recognition = document.querySelector('.recognition'); //獲取人臉識別的按鈕

    var close = document.querySelector('.close');
    var notice = document.querySelector('.notice');
    var canvas = document.querySelector('.draw_img');
    var context = canvas.getContext('2d');
    var buffer;

    open.onclick = invokingCamera;  //回調函數 函數名稱加括號是主動執行
    recognition.onclick = screenShot;  //點擊人臉識別
    close.onclick = function () {
        //console.log(buffer);
        buffer && buffer.getTracks()[0].stop(); //停止視頻流
        //console.log(buffer);
    }
    //獲取攝像頭,獲取流媒體數據
    function invokingCamera() {
        if (navigator.mediaDevices.getUserMedia) {
            //優先使用前置攝像頭
            navigator.mediaDevices.getUserMedia({audio: false, video: {facingMode: "user"}}).then(
                //獲取視頻流數據 成功後
                function (MediaStream) {
                    //console.log(stream);
                    buffer = MediaStream; //會指向一個內存地址
                    //console.log(buffer);
                    capture.srcObject = MediaStream;
                    capture.onloadedmetadata = function(e) {
                        capture.play();
                    };
                }
            ).catch(
                //失敗後
                function (err) {
                    console.log(err.name + ": " + err.message);
                }
            );
        } else {
            alert('您的瀏覽器不支持攝像頭');
        }
    }

    function screenShot() {
        msg('正在檢測,請稍後~~~', '#c665ff');
        context.drawImage(capture,0,0,200,150);
        new Post({
            url: '/judge',
            data:canvas.toDataURL('image/png'),
            success: function (res) {
                 console.log(res); //服務器發送的消息
                res = JSON.parse(res).result.score;
                console.log(typeof res);
                if (res > 85) {
                    msg('歡迎主人~', '#7ef6c7');
                } else {
                    msg('醜拒~~', '#f10d0f');
                }
            }
        })
    }

    function msg(con, color) { //輸出信息
        notice.innerHTML = con + '';
        notice.style.color = color;
    }

    //post 方式傳輸數據 get的話 base64 5mb url
    function Post(opt) {
        //構造函數
        this.init(opt);
    }

    Post.prototype = {
        init: function (opt) {  //初始化 參數 URL地址 Data參數 method方式
            this.url = opt.url || '';
            this.data = opt.data || {};
            this.method = 'POST';
            this.async = true;//異步
            this.success = opt.success || function () {  //回調函數
            }
            this.xhr();
        },
        xhr: function () {
            var that = this;
            var xhr = new XMLHttpRequest();//ajax對象實例化
            console.log(this.data)
            //請求的類型  請求地址 異步或者同步
            xhr.open(this.method, this.url, this.async);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8'); //表頭
            xhr.send('img='+this.data);
            xhr.onreadystatechange = function (ev) {
                if (xhr.status === 200 && xhr.readyState === 4) {
                    this.success(xhr.response);//回調數據
                }
            }.bind(this);
        }
    }
    new Post({
        url: '/access',
        data:'',
    })
</script>
</body>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章