2018-05-05
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 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>