在支付寶推出的刷臉系統(tǒng)開始變得流行火爆起來,這就帶動不少的人來學(xué)習(xí)這個效果,那么今天小編和大家分享有關(guān)于“使用HTML5+tracking.js實(shí)現(xiàn)刷臉支付功能方法!實(shí)例分析!”這個方面的相關(guān)內(nèi)容吧!
1.攝像頭1.1input獲取攝像頭
html5中獲取用戶攝像頭,有兩種方式,使用input,如下:
<input type="file" capture="camera" accept="image/*"/>
另外如果想打開相冊,可以這樣:
<input type="file" accept="img/*">
但是這兩種方式都會有兼容性問題,用過的同學(xué)可能都知道。
1.2getUserMedia獲取攝像圖
getUserMedia是html5一個新的api,官方一點(diǎn)的定義是:
MediaDevices.getUserMedia()
會提示用戶給予使用媒體輸入的許可,媒體輸入會產(chǎn)生一個MediaStream
,里面包含了請求的媒體類型的軌道。此流可以包含一個視頻軌道(來自硬件或者虛擬視頻源,比如相機(jī)、視頻采集設(shè)備和屏幕共享服務(wù)等等)、一個音頻軌道(同樣來自硬件或虛擬音頻源,比如麥克風(fēng)、A/D轉(zhuǎn)換器等等),也可能是其它軌道類型。
簡單一點(diǎn)說就是可以獲取到用戶攝像頭。
同上面input一樣,這種方式也有兼容性問題,不過可以使用其他方式解決,這里可以參考 1.3播放視屏 獲取設(shè)備方法有兩個回調(diào)函數(shù),一個是成功,一個是失敗。成功了就開始播放視頻,播放視屏其實(shí)就是給video設(shè)置一個url,并調(diào)用play方法,這里設(shè)置url要考慮不同瀏覽器兼容性,代碼如下: 注意: 2. 捕捉人臉 2.1使用tracking.js捕捉人臉 視屏在video中播放成功之后就開始識別人臉了,這里使用到一個第三方的功能tracking.js,是國外的大神寫的JavaScript圖像識別插件。關(guān)鍵代碼如下: 捕獲到人臉之后,可以在頁面上用一個小方框標(biāo)注出來,這樣有點(diǎn)交互效果。 在頁面中畫一些方框,標(biāo)識出人臉: 2.2拍照 拍照,就是使用video作為圖片源,在canvas中保存一張圖片下來,注意這里使用toDataURL方法的時候可以設(shè)置第二個參數(shù)quality,從0到1,0表示圖片比較粗糙,但是文件比較小,1表示品質(zhì)最好。 拍照完成之后就可以把文件發(fā)送給后端,讓后端進(jìn)行對比驗(yàn)證,這里后端使用的是阿里云的接口。 3.最后效果 3.1參考代碼demo 最后,demo我已經(jīng)放在github上了,感興趣可以打開看一下。 效果如下: 3.2在項目中落地 最后放在項目中,無非就是最后一個步驟,去調(diào)用接口比對,根據(jù)比對結(jié)果成功是成功還是失敗,決定是人臉支付還是繼續(xù)使用原來的密碼支付,效果如下: ps:這里人臉比對失敗了,是因?yàn)槲規(guī)е谡?,就不呲牙露臉了?/p>
總結(jié) 那么這就是今天我們有關(guān)于“使用HTML5+tracking.js實(shí)現(xiàn)刷臉支付功能方法!”這個內(nèi)容文章的分享,更多的相關(guān)內(nèi)容我們都可以在W3Cschool這里面進(jìn)行學(xué)習(xí)和了解!// 訪問用戶媒體設(shè)備
getUserMedia(constrains, success, error) {
if (navigator.mediaDevices.getUserMedia) {
//最新標(biāo)準(zhǔn)API
navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error);
} else if (navigator.webkitGetUserMedia) {
//webkit內(nèi)核瀏覽器
navigator.webkitGetUserMedia(constrains).then(success).catch(error);
} else if (navigator.mozGetUserMedia) {
//Firefox瀏覽器
navagator.mozGetUserMedia(constrains).then(success).catch(error);
} else if (navigator.getUserMedia) {
//舊版API
navigator.getUserMedia(constrains).then(success).catch(error);
} else {
this.scanTip = "你的瀏覽器不支持訪問用戶媒體設(shè)備"
}
}
success(stream) {
this.streamIns = stream
// 設(shè)置播放地址,webkit內(nèi)核瀏覽器
this.URL = window.URL || window.webkitURL
if ("srcObject" in this.$refs.refVideo) {
this.$refs.refVideo.srcObject = stream
} else {
this.$refs.refVideo.src = this.URL.createObjectURL(stream)
}
this.$refs.refVideo.onloadedmetadata = e => {
// 播放視頻
this.$refs.refVideo.play()
this.initTracker()
}
},
error(e) {
this.scanTip = "訪問用戶媒體失敗" + e.name + "," + e.message
}
// 人臉捕捉
initTracker() {
this.context = this.$refs.refCanvas.getContext("2d") // 畫布
this.tracker = new tracking.ObjectTracker(['face']) // tracker實(shí)例
this.tracker.setStepSize(1.7) // 設(shè)置步長
this.tracker.on('track', this.handleTracked) // 綁定監(jiān)聽方法
try {
tracking.track('#video', this.tracker) // 開始追蹤
} catch (e) {
this.scanTip = "訪問用戶媒體失敗,請重試"
}
}
// 追蹤事件
handleTracked(e) {
if (e.data.length === 0) {
this.scanTip = '未檢測到人臉'
} else {
if (!this.tipFlag) {
this.scanTip = '檢測成功,正在拍照,請保持不動2秒'
}
// 1秒后拍照,僅拍一次
if (!this.flag) {
this.scanTip = '拍照中...'
this.flag = true
this.removePhotoID = setTimeout(() => {
this.tackPhoto()
this.tipFlag = true
}, 2000)
}
e.data.forEach(this.plot)
}
}
<div class="rect" v-for="item in profile"
:style="{ width: item.width + 'px', height: item.height + 'px', left: item.left + 'px', top: item.top + 'px'}"></div>
// 繪制跟蹤框
plot({x, y, width: w, height: h}) {
// 創(chuàng)建框?qū)ο? this.profile.push({ width: w, height: h, left: x, top: y })
}
// 拍照
tackPhoto() {
this.context.drawImage(this.$refs.refVideo, 0, 0, this.screenSize.width, this.screenSize.height)
// 保存為base64格式
this.imgUrl = this.saveAsPNG(this.$refs.refCanvas)
// this.compare(imgUrl)
this.close()
},
// Base64轉(zhuǎn)文件
getBlobBydataURI(dataURI, type) {
var binary = window.atob(dataURI.split(',')[1]);
var array = [];
for(var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {
type: type
});
},
// 保存為png,base64格式圖片
saveAsPNG(c) {
return c.toDataURL('image/png', 0.3)
}