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>