基於HTML5 的人臉識別活體認證

来源:http://www.cnblogs.com/lilies/archive/2016/06/21/5604212.html
-Advertisement-
Play Games

近幾年,人臉識別技術在身份認證領域的應用已經有了較多應用,例如:支付寶、招行的取款、養老金領取等方面,但在杜絕假冒、認證安全性等方面,目前還是一個比較需要進一步解決的課題,特別是在移動端的活體認證技術方面。 本文介紹了在HTML5 環境下可以採用clmtrackr.js 檢測工具,結合人臉模型,實現 ...


近幾年,人臉識別技術在身份認證領域的應用已經有了較多應用,例如:支付寶、招行的取款、養老金領取等方面,但在杜絕假冒、認證安全性等方面,目前還是一個比較需要進一步解決的課題,特別是在移動端的活體認證技術方面。

本文介紹了在HTML5 環境下可以採用clmtrackr.js 檢測工具,結合人臉模型,實現人臉的跟蹤檢測。同時採用動作識別實現活體認證。

但本方案只能夠在Firefox 或者Chrome中使用。並且只適合研究學習,實際場景中不太理想,需要進一步優化才能夠應用。

如果有人有相關的技術,可以推薦介紹給我。

<!DOCTYPE html>
<!--
Ideally these elements aren't created until it's confirmed that the 
client supports video/camera, but for the sake of illustrating the 
elements involved, they are created with markup (not JavaScript)
-->
<html>
<meta charset="GBK">
<style>
#container {
position : relative;
}

#canvas {
position : absolute;
left : 0;
top : 0;
}
</style>
<script src="utils.js"></script>
<script src="clmtrackr.js"></script>
<script src="./models/model_pca_20_svm.js"></script>
<script src="numeric.js"></script>
<script src="ccv.js"></script>

<audio id="media"> 
你的瀏覽器不支持audio標簽。
</audio>
<div id="container">
<video id="video" width="600" height="400" autoplay > 
您的瀏覽器不支持video標簽
</video>
<canvas id="canvas" width="600" height="400"></canvas>
</div>    

<button id="snap">Snap Photo</button>

<button id="start">Start</button>

<button id="showposition">顯示</button>

<button id="hideposition">不顯示</button>

<br/>

<button id="mouse">張嘴驗證</button> 
<button id="head">搖頭驗證</button> 
<button id="eye">眨眼驗證</button>


<div id="tip">
</div>
<div id="result">
</div>
<div id="msg">
</div>

<div id="positions">
</div>

<script>

var showpos=false;
// Put event listeners into place
//window.addEventListener("DOMContentLoaded", function() {

// Grab elements, create settings, etc.
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
video = document.getElementById("video"),
videoObj = { "video": true },
errBack = function(error) {
if (error.PERMISSION_DENIED) {
jAlert('用戶拒絕了瀏覽器請求媒體的許可權', '提示');
} else if (error.NOT_SUPPORTED_ERROR) {
jAlert('對不起,您的瀏覽器不支持拍照功能,請使用其他瀏覽器', '提示');
} else if (error.MANDATORY_UNSATISFIED_ERROR) {
jAlert('指定的媒體類型未接收到媒體流', '提示');
} else {
jAlert('系統未能獲取到攝像頭,請確保攝像頭已正確安裝。或嘗試刷新頁面,重試', '提示');
}
};

// Put video listeners into place
if(navigator.getUserMedia) { // Standard

navigator.getUserMedia(videoObj, function(stream) {

video.src = stream;
video.play();

}, errBack);

} else if(navigator.webkitGetUserMedia) { // WebKit-prefixed

try{

navigator.webkitGetUserMedia(videoObj, function(stream){ 
video.src = window.webkitURL.createObjectURL(stream);
video.play();
}, errBack);

}catch(error){
alert(error);
}

}
else if(navigator.mozGetUserMedia) { // Firefox-prefixed
navigator.mozGetUserMedia(videoObj, function(stream){

video.src = window.URL.createObjectURL(stream);
video.play();
}, errBack);
}



// Trigger photo take
document.getElementById("snap").addEventListener("click", function() {
context.drawImage(video, 0, 0, 600, 400);
});
document.getElementById("start").addEventListener("click", function() {
startTrack();
});


document.getElementById("showposition").addEventListener("click", function() {
showpos=true;
});

document.getElementById("hideposition").addEventListener("click", function() {
showpos=false;
});

document.getElementById("mouse").addEventListener("click", function() {
alive_mouse();
});
document.getElementById("head").addEventListener("click", function() {
alive_head();
});

document.getElementById("eye").addEventListener("click", function() {
alive_eye();
});




//}, false);


</script>

<script>

//////////////////////////////////////////////////////////////////////////////
//活體
var last_time=0;//時間因素
var last_nose_left=0;
var last_nose_top=0;

//張嘴動作
var is_mouse_ok=false; 
var is_alive_mouse=false;
var last_dis_eye_norse=0;
var last_dis_mouse=0;
function alive_mouse(){

var media = document.getElementById("media");
media.src="mp3/alive_mouse.mp3";
media.play();

document.getElementById("tip").innerHTML="請張合嘴巴";
document.getElementById('result').innerHTML = "";

is_mouse_ok=false;
last_dis_mouse=0;
last_time=0;
last_dis_eye_norse=100000000; 

is_alive_head=false;
is_alive_mouse=true;
is_alive_eye=false;

}
//搖頭動作
var is_head_ok=false; 
var is_alive_head=false;
var last_dis_left_right=100000000; 
function alive_head(){

var media = document.getElementById("media");
media.src="mp3/alive_head.mp3";
media.play();

document.getElementById("tip").innerHTML="請在水平方向左右搖頭";
document.getElementById('result').innerHTML = "";

is_head_ok=false;
last_dis_left_right=100000000; 
last_time=0; 
is_alive_head=true;
is_alive_mouse=false;
is_alive_eye=false;

}

//眨眼動作
var is_alive_eye=false;
var is_eye_ok = false;

function alive_eye(){
var media = document.getElementById("media");
media.src="mp3/alive_eye.mp3";
media.play();

document.getElementById("tip").innerHTML="請眨眼";
document.getElementById('result').innerHTML = "";

is_eye_ok=false;
last_dis_eye_norse=100000000; 

last_nose_left=0;
last_nose_top=0;

last_time=0; 

is_alive_head=false;
is_alive_mouse=false;
is_alive_eye=true;
}


function startTrack(){

var videoInput = document.getElementById('video');

var ctracker = new clm.tracker();
ctracker.init(pModel);
ctracker.start(videoInput);


var canvasInput = document.getElementById('canvas');
var cc = canvasInput.getContext('2d');
cc.lineWidth=3;

function drawLoop() {
//requestAnimationFrame(drawLoop);


cc.clearRect(0, 0, canvasInput.width, canvasInput.height);
//ctracker.draw(canvasInput );
var positions = ctracker.getCurrentPosition();
if (showpos && positions) {

for (var p = 0;p < positions.length;p++) {
positionString += "featurepoint "+p+" : ["+positions[p][0].toFixed(2)+","+positions[p][1].toFixed(2) +"]<br/>";
}
document.getElementById('positions').innerHTML = positionString;


}
if(positions){

for (var p =0;p < 71;p++) {    
cc.beginPath();
cc.arc(positions[p][0].toFixed(2), positions[p][1].toFixed(2),2, 0, Math.PI * 2, true);
cc.closePath();
cc.fillStyle = '#00FF00';
cc.fill();
}


//cc.strokeStyle = 'red';

//0-14 輪廓
//7 下吧,最下

//2 最左邊
//12 最右邊


//15-22 眉毛


//23-27 左眼睛五個點
//27 左眼中間
//63-66 左眼四個點

//28-32 右眼睛五個點
//67-70 右眼四個點


//33-43 鼻子
//62 鼻中間


//44-61 嘴巴
//47 嘴巴上
//53 嘴巴下

///////////////////////////////////////////////////////////////////////////////////////////////

//左眼中間
for (var p =27;p <=27;p++) {    
cc.beginPath();
cc.arc(positions[p][0].toFixed(2), positions[p][1].toFixed(2), 2, 0, Math.PI * 2, true);
cc.closePath();
cc.fillStyle = 'red';
cc.fill();
}

//鼻子中間
for (var p =62;p <=62;p++) {    
cc.beginPath();
cc.arc(positions[p][0].toFixed(2), positions[p][1].toFixed(2), 2, 0, Math.PI * 2, true);
cc.closePath();
cc.fillStyle = 'red';
cc.fill();
}
//嘴巴上
for (var p =57;p <=57;p++) {    
cc.beginPath();
cc.arc(positions[p][0].toFixed(2), positions[p][1].toFixed(2), 2, 0, Math.PI * 2, true);
cc.closePath();
cc.fillStyle = 'red';
cc.fill();
}
//嘴巴下
for (var p =60;p <=60;p++) {    
cc.beginPath();
cc.arc(positions[p][0].toFixed(2), positions[p][1].toFixed(2), 2, 0, Math.PI * 2, true);
cc.closePath();
cc.fillStyle = 'red';
cc.fill();
}
//////////////////////////////////////
//head
if(is_alive_head==true){
if(last_time==0 || (new Date().getTime()-last_time>500 && new Date().getTime()-last_time<10000 ) ){
var xdiff_left = positions[62][0] - positions[2][0] ;
var ydiff_left = positions[62][1] - positions[2][1] ;
var dis_left = Math.pow((xdiff_left * xdiff_left + ydiff_left * ydiff_left), 0.5);

var xdiff_right = positions[12][0] - positions[62][0] ;
var ydiff_right = positions[12][1] - positions[62][1] ;
var dis_right = Math.pow((xdiff_right * xdiff_right + ydiff_right * ydiff_right), 0.5);

var xdiff_side = positions[12][0] - positions[2][0] ;
var ydiff_side = positions[12][1] - positions[2][1] ;
var dis_side = Math.pow((xdiff_side * xdiff_side + ydiff_side * ydiff_side), 0.5);


var dis_left_right = dis_left - dis_right;
document.getElementById('result').innerHTML = dis_left_right;


if(last_dis_left_right>0 && dis_left_right > dis_side/3){

document.getElementById('result').innerHTML = "通過";

is_head_ok=true;
is_alive_head=false;

}



last_dis_left_right=dis_left_right; 
last_time = new Date().getTime();

}
}

/////////////////////////////////////
//mouse 
if(is_alive_mouse==true){
if(last_time==0 || (new Date().getTime()-last_time>500 && new Date().getTime()-last_time<10000 ) ){

//研究和鼻子距離
var xdiff = positions[62][0] - positions[27][0] ;
var ydiff = positions[62][1] - positions[27][1] ; 
var dis_eye_norse = Math.pow((xdiff * xdiff + ydiff * ydiff), 0.5);

//上嘴唇 和下嘴唇距離
var xdiff_mouse = positions[53][0] - positions[47][0] ;
var ydiff_mouse = positions[53][1] - positions[47][1] ; 
var dis_mouse = Math.pow((xdiff_mouse * xdiff_mouse + ydiff_mouse * ydiff_mouse), 0.5);

//上次的眼鼻距離和這次的眼鼻距離差
var dn= Math.abs(dis_eye_norse-last_dis_eye_norse);

//上次的嘴距離和本次的嘴距離差
var dm=Math.abs(dis_mouse - last_dis_mouse);




//鼻子的位置確保變化不大
if(last_nose_left>0 && last_nose_top>0
&& Math.abs(positions[62][0]-last_nose_left)<5
&& Math.abs(positions[62][1]-last_nose_top)<5
){

document.getElementById('msg').innerHTML = dn;

if(last_dis_eye_norse>0 && dn < dis_eye_norse*1/50){ 

if(last_dis_mouse>0 && dm > dis_mouse/10){

document.getElementById('result').innerHTML = "通過";

is_alive_mouse=false;
is_mouse_ok=true;
}

}
}


last_dis_mouse = dis_mouse;
last_dis_eye_norse = dis_eye_norse;
last_time = new Date().getTime(); 

last_nose_left = positions[62][0];
last_nose_top = positions[62][1];

}
}

/////////////////////////////////////
//eye 
if(is_alive_eye==true){
if(last_time==0 || (new Date().getTime()-last_time>10 ) ){


var xdiff1 = positions[62][0] - positions[27][0] ;
var ydiff1 = positions[62][1] - positions[27][1] ; 
var dis_eye_norse1 = Math.pow((xdiff1 * xdiff1 + ydiff1 * ydiff1), 0.5);

var xdiff2 = positions[62][0] - positions[32][0] ;
var ydiff2 = positions[62][1] - positions[32][1] ; 
var dis_eye_norse2 = Math.pow((xdiff2 * xdiff2 + ydiff2 * ydiff2), 0.5);

var dis_eye_norse = (dis_eye_norse1 + dis_eye_norse2);



if(last_nose_left>0 && last_nose_top>0
&& Math.abs(positions[62][0]-last_nose_left)<0.5
&& Math.abs(positions[62][1]-last_nose_top)<0.5
){
document.getElementById('msg').innerHTML = Math.abs(dis_eye_norse - last_dis_eye_norse) - dis_eye_norse*1/20;

if(last_dis_eye_norse>0 && (Math.abs(dis_eye_norse - last_dis_eye_norse) > dis_eye_norse*1/20 ) ){

document.getElementById('result').innerHTML = "通過";

is_alive_eye=false;
is_eye_ok=true;

}
}


last_nose_left = positions[62][0];
last_nose_top = positions[62][1];

last_dis_eye_norse = dis_eye_norse;
last_time = new Date().getTime(); 

}


}


}

requestAnimationFrame(drawLoop);

}

drawLoop();

}

 

</script>
</html>

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • <script type="text/javascript"> function getRandom(n,m){ var n=Number(n); //強制轉換成數字 var m=Number(m); if(isNaN(n)||isNaN(m)){ //判斷是否為有效數字 ,其中一個不是有效數字就返 ...
  • 對於javascript程式員來說,發送ajax請求獲取後臺數據然後把數據和模板拼接成字元串渲染回DOM實現無刷新更新頁面這樣的操作可謂是輕車熟路。但眾所周知,ajax有一個不好,就是不能跨域傳輸數據,而跨域傳輸有時候又是必須用到的,比如我們可能需要調用第三方網站提供的某些API來獲取某些信息,提供 ...
  • 恢復內容開始 最近在上海上學的一個高中同學讓我幫忙,幫她做她們的電腦課程大作業。 由於關係不錯我也不好意思拒絕就幫忙做了,因為這個學期剛剛開始接觸HTML5和css,所以製作過程中有很多不懂的,而且由於HTML5是選修課,一星期只有一節,所以做這個花費了比較多的時間,這個網站是我製作的第一個網站, ...
  • 1.popup中添加圖表信息 2.echat以控制項形式添加在map中 3.以marker形式添加在map demo源碼地址:https://github.com/shitao1988/leaflet-echartmarker ...
  • CONTENT(目錄) 前言 Variable declearation:three rules you can break 1.Don't set var statement in a block 2.Don't set var statement in a loop 3.Set a variab ...
  • 前言: 1.HTML5的發展非常迅速,可以說已經是前端開發人員的標配,在電商類型的APP中更是運用廣泛,這個系列的文章是本人自己整理,儘量將開發中不常用到的剔除,將經常使用的拿出來,使需要的朋友能夠真正快速入門,如果有哪些不清楚的地方或者錯誤,歡迎聯繫我 2.更新時間沒有規律,一般會在3天左右更新一 ...
  • 在現在的很多頁面中,都運用到了百度地圖來定位,例如: 像這樣的地圖,我們可以通過手動來進行放大、縮小、移動等來查找具體的地址,特別方便,在頁面上引用也顯得頁面很有特點,那麼,應該怎麼樣來製作這種地圖呢? 一、獲取源代碼 網址:http://api.map.baidu.com/lbsapi/creat ...
  • 閉包(closure)是Javascript語言的一個難點,也是它的特色,很多高級應用都要依靠閉包實現。 一、變數的作用域 要理解閉包,首先必須理解Javascript特殊的變數作用域。 變數的作用域無非就是兩種:全局變數和局部變數。 Javascript語言的特殊之處,就在於函數內部可以直接讀取全 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...