工具系列 | H5如何实现人脸识别
时间:2022-07-22
本文章向大家介绍工具系列 | H5如何实现人脸识别,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
背景
人脸识别技术在当下已经十分成熟,但主要在移动端和专有设备应用上较为普及,而在Web端并不多见,本着学习的目的从零实现web端的人脸登录功能。
视频流
使用navigator.getUserMedia方法在浏览器中获取视频流+音频流(通过摄像头麦克风),将来可以用于获取任意数据流,比如光盘和传感器。
识别工具
百度人脸识别库
1、分析图片中人脸的遮挡度、模糊度、光照强度、姿态角度、完整度、大小等特征,基于输出的符合质量标准的图片,返回准确的相似度评分 2、比对图片中两张人脸的相似度,并返回相似度分值 3、支持生活照、证件照、身份证芯片照、带网纹照4种图片类型的人脸对比 4、分析单张图片中人像的破绽(摩尔纹、成像畸形等),判断图片中目标对象否为真人,确保比对效果真实可靠
face_recognition
被称为世界上最简单的人脸识别库(使用确实超简单)。你可以通过Python引用或者命令行的形式使用它,来管理和识别人脸。 该软件包使用dlib中最先进的人脸识别深度学习算法,使得识别准确率在《Labled Faces in the world》测试基准下达到了99.38%。 它同时提供了一个叫face_recognition的命令行工具,以便你可以用命令行对一个文件夹中的图片进行识别操作。
总体流程
- 启动web服务,使用face_recognition将基础库图片进行建模,将建模结果(识别到的人脸在图片中的位置和人脸特征)加载到内存。
- 前端通过h5页面的getUserMedia方法调用摄像头获取视频流。
- 通过canvas抓取一帧视频转化为图片(base64),使用http或websocket发送到后台。
- 后台接受base64参数并转化为图片保存。
- 调用face_recognition.locations和face_recognition.face_encodings进行图片建模。
- 调用face_recognition.compare_faces将图片建模结果与基础库结果比对。
- 根据定义的比对阈值(被称为容忍度,一般为0.6)返回比对结果,如果阈值小于该值,判断是该用户,认定允许登录,返回系统界面。否则返回人脸识别失败的信息。
流程图
时序图
参考案例
前段代码
<div class="layui-container">
<div class="blog-main">
<!-- 左边区域 -->
<div id="support"></div>
<div class="div-a" id="contentHolder">
<video id="video" width="100%" height="60%" autoplay></video>
<canvas hidden="hidden" id="canvas" width="520" height="250"></canvas>
</div>
<div class="div-b">
<!-- <input type="button" id="snap" style="width:100px;height:35px;" value="拍 照" />
<input type="button" onclick="CatchCode();" style="width:100px;height:35px;" value="上传服务器" /> -->
<h3>检测实时数据</h3>
<span>年龄:</span><span id="age"></span><br />
<span>颜值:</span><span id="beauty"></span><br />
<span>性别:</span><span id="gender"></span><br />
<span>人种:</span><span id="race"></span><br />
<span>是否戴眼镜:</span><span id="glasses"></span><br />
<span>表情:</span><span id="expression"></span><br />
</div>
</div>
</div>
<script>
//判断浏览器是否支持HTML5 Canvas
window.onload = function () {
try {
//动态创建一个canvas元 ,并获取他2Dcontext。如果出现异常则表示不支持 document.createElement("canvas").getContext("2d");
document.getElementById("support").innerHTML = "浏览器支持HTML5 CANVAS";
}
catch (e) {
document.getElementByIdx("support").innerHTML = "浏览器不支持HTML5 CANVAS";
}
};
var timer = null;
//这段代 主要是获取摄像头的视频流并显示在Video 签中
window.addEventListener("DOMContentLoaded", function () {
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
video = document.getElementById("video"),
// videoObj = { "video": true },
//调用用户媒体设备,访问摄像头
mediaConstraints = {
audio: false,
video: {
width: { ideal: 1280 },
height: { ideal: 720 },
frameRate: {
ideal: 10,
max: 15
},
facingMode: "environment"
}
};
errBack = function (error) {
console.log("Video capture error: ", error.code);
};
//拍照按钮
// $("#snap").click(function () {
// context.drawImage(video, 0, 0, 330, 250);
// })
//拍照每秒一次
timer = setInterval(function () {
context.drawImage(video, 0, 0, 330, 250)
CatchCode();
}, 3000);
//navigator.getUserMedia这个写法在Opera中好像是navigator.getUserMedianow
//更新兼容火狐浏览器
if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
navigator.getUserMedia(mediaConstraints, function (stream) {
video.srcObject = stream;
video.play();
}, errBack);
}
}, false);
/**
* Base64 数据处理
*/
function dataURItoBlob(base64Data) {
var byteString;
if (base64Data.split(',')[0].indexOf('base64') >= 0)
byteString = atob(base64Data.split(',')[1]);
else
byteString = unescape(base64Data.split(',')[1]);
var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], { type: mimeString });
}
/**
* 上传服务器
*/
function CatchCode() {
var canvans = document.getElementById("canvas");
//获取浏览器页面的画布对象
//以下开始编 数据
var imageBase64 = canvans.toDataURL();
var blob = dataURItoBlob(imageBase64);
var fd = new FormData(document.forms[0]);
fd.append("the_file", blob, 'image.png');
//将图像转换为base64数据
$.ajax({
type: "POST",
url: "{:url('/index/Index/faceVerifyVideo')}",
processData: false, // 必须
contentType: false, // 必须
data: fd,
datatype: "json",
success: function (res) {
console.log(res);
if (res.code == 0) {
// layer.msg(JSON.stringify(res.data.face_list));
var jsonObj = res.data.face_list[0];
var age = jsonObj.age;
var beauty = jsonObj.beauty;
var gender = jsonObj.gender;
var race = jsonObj.race;
var glasses = jsonObj.glasses;
var expression = jsonObj.expression
$("#age").html(age);
$("#beauty").html(beauty);
if (gender.type == 'male') {
$("#gender").html("男");
} else {
$("#gender").html("女");
}
if (race.type == 'yellow') {
$("#race").html("黄种人");
} else if (race.type == 'white') {
$("#race").html("白种人");
} else if (race.type == 'black') {
$("#race").html("黑种人 ");
} else {
$("#race").html("阿拉伯人");
}
if (glasses.type == 'none') {
$("#glasses").html("未戴眼镜");
} else if (glasses.type == 'common') {
$("#glasses").html("戴了普通眼镜");
} else {
$("#glasses").html("戴了墨镜");
}
if (expression.type == 'none') {
$("#expression").html("不笑");
} else if (expression.type == 'smile') {
$("#expression").html("微笑");
} else {
$("#expression").html("大笑");
}
// layer.alert(res.msg, { icon: 6 });
clearInterval(timer);
} else {
layer.msg(res.msg, { icon: 5 });
}
},
error: function () {
layer.alert('接口异常', { icon: 5 });
}
});
}
</script>
服务端代码
微信公众号好回复 百度人脸识别代码
获取
- vue-cli#2.0 webpack 配置分析
- 短代码插件S-shortcodes 更新2.4版本:修复font icon的冲突问题
- 景驰落户广州 王劲称不知百度为何指控 四条回应两大疑点
- 全球各行业2020年将需要270万位数据科学家
- 解决iOS 版Safari 中浮动(float)导致页面右侧偏移的bug
- 学而思网校又玩大了:引入人工智能技术,办了一场“人机对话”英语赛事
- 全球首个机器人公民索菲亚亮相2017双12知商节 引爆全场知识产权新高潮
- WP Settings Generator:生成WordPress设置相关代码的工具
- Reactjs 入门基础(三)
- 小谈中文环境下中文排版的font-family 字体选择
- WordPress 的几个高级调试( Debug)技巧
- Customizer Library:主题“自定义”功能的WordPress类库
- Reactjs 入门基础(二)
- WordPress中当评论审核通过时候给评论者发邮件
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 深入浅出mongodb(二)
- 算法——快速排序
- 算法——二分查找算法
- 第一篇——Ubuntu 安装 Elasticsearch
- Ubuntu安装Redis(手动编译)
- 第五节:Activiti6.0——流程定义相关API
- 第四节:Activiti6.0——使用zip、bpmn代码生成流程图的资源部署以及资源的查询
- 第三节:Activiti6.0——Query的API使用
- 第二节:Activiti6.0配置文件的读取
- SpringMvc配置文件上传
- 使用web.xml配置SpringMvc(使用Java加载配置)
- SpringMVC配置字符过滤器的两种方式
- SpringMvc使用Json(Java配置方式)
- 使用IDEA创建SpringMvc并整合Thymeleaf(Java配置版)
- Junit报错:Argument(s) are different! Wanted: