JavaScript實(shí)現(xiàn)人體面部活體檢測的功能
實(shí)現(xiàn)高可靠度的人臉活體檢測(Liveness Detection)并非僅僅是前端 JavaScript 就能輕松完成的,需要借助較為復(fù)雜的算法、深度模型推理(通常需要 WebAssembly 或 WebGPU 等技術(shù)加持),并且需要結(jié)合多種檢測策略(眨眼、頭部姿態(tài)、光照變化、深度信息等)才能實(shí)現(xiàn)相對穩(wěn)定的活體檢測效果。在瀏覽器端用純 JavaScript(或附加 WebAssembly/WebGPU)進(jìn)行基礎(chǔ)的人臉活體檢測技術(shù)上是可行的,但如果對安全性和準(zhǔn)確度有很高要求,往往還需配合后端算法或服務(wù)端驗(yàn)證流程。
一、活體檢測的核心原理
人臉活體檢測的目標(biāo)是判斷當(dāng)前攝像頭前的人臉是否是真實(shí)活人,而不是照片、視頻或電子屏幕的翻拍。常見的檢測策略包括以下幾類,可單獨(dú)或組合使用:
基于動作要求的檢測(Challenge-Response)
- 讓用戶做出隨機(jī)指定的動作(眨眼、點(diǎn)頭、張嘴、左看右看等),并使用人臉特征點(diǎn)跟蹤來判斷動作是否真實(shí)發(fā)生。
- 如果僅是簡單的“眨眼”,有時(shí)可能會被視頻模擬欺騙(提前錄制了眨眼視頻),所以會讓用戶做多步動作或隨機(jī)動作序列,增加偽造難度。
基于光照/反射分析的檢測
- 分析人臉在不同光照條件下的變化(如可見光或近紅外),例如檢測皮膚表層反射或血液流動變化(rPPG:remote Photoplethysmography),但在純 JavaScript 和普通 RGB 攝像頭環(huán)境下難度較大,而且設(shè)備差異很大。
基于三維結(jié)構(gòu)的檢測
- 通過檢測面部關(guān)鍵點(diǎn)在不同角度的微小變化,估算面部三維結(jié)構(gòu)(類似于深度估計(jì)),從而判斷是否為平面照片。
- 有些高端手機(jī)/平板(如支持Face ID的蘋果設(shè)備)會使用紅外結(jié)構(gòu)光進(jìn)行三維建模,這種硬件層面的檢測最為可靠。
基于深度學(xué)習(xí)模型的檢測
- 使用 CNN、Vision Transformer 等深度學(xué)習(xí)模型,直接把攝像頭采集到的人臉幀輸入模型中,由模型輸出“是真實(shí)人臉”還是“翻拍/假人臉”。
- 這一類模型在推理計(jì)算上可能比較復(fù)雜,需在瀏覽器端配合 WebAssembly(如 ONNX Runtime Web、TensorFlow.js)或 WebGPU 才能保證實(shí)時(shí)性。
二、在 JavaScript 中實(shí)現(xiàn)活體檢測的可行方案
1. 使用現(xiàn)有的前端人臉檢測/識別庫并擴(kuò)展
Face-api.js
- 主要用于人臉檢測、識別、表情識別以及面部關(guān)鍵點(diǎn)定位,可在瀏覽器端運(yùn)行(基于 TensorFlow.js)。
- 你可以基于 face-api.js 的關(guān)鍵點(diǎn)定位功能,做初步的眨眼檢測、張嘴檢測、頭部角度變化檢測等簡單挑戰(zhàn)。
MediaPipe(Web 拓展)
- Google 的開源項(xiàng)目 MediaPipe,提供了 Web 版本的 Face Mesh,可跟蹤面部 468 個(gè)關(guān)鍵點(diǎn),用于測量面部區(qū)域。
- 基于關(guān)鍵點(diǎn)數(shù)據(jù),你可以做動作檢測(眨眼、張嘴、擺頭)、面部姿態(tài)估計(jì)等,從而完成基礎(chǔ)的動作活體檢測。
這些庫能在純前端進(jìn)行人臉關(guān)鍵點(diǎn)檢測,但如何區(qū)分真臉和偽造仍需要你在這些基礎(chǔ)能力之上自己設(shè)計(jì)或引入更復(fù)雜的算法(如深度估計(jì)、光照檢測或深度學(xué)習(xí)模型)。
2. 集成深度學(xué)習(xí)推理框架(WebAssembly / WebGPU)
- ONNX Runtime Web 或 TensorFlow.js
- 這類框架支持將預(yù)訓(xùn)練好的活體檢測模型(一般是 ONNX 模型或 TensorFlow SavedModel)放到瀏覽器內(nèi)做推理。
- 當(dāng)你獲取到攝像頭的幀后,可以將圖像數(shù)據(jù)送入模型進(jìn)行二分類:[“活體”、“假體”]。
- 由于活體檢測模型往往對推理速度要求較高,需要在瀏覽器中啟用 WebAssembly(CPU 加速)或 WebGPU(更快的硬件加速)。
- 這樣做的好處是前后端都可以把推理放在本地完成,無需上傳視頻流到后端,保護(hù)用戶隱私;壞處是客戶端設(shè)備性能不同,可能會導(dǎo)致模型運(yùn)行速度差異大,而且模型也容易被逆向(安全性存在一定隱患)。
3. 與后端服務(wù)協(xié)同
- 純前端方案在安全性和性能上都有局限,更常見的做法是“前端采集 + 簡單預(yù)處理 + 后端高精度檢測”。
- 前端只負(fù)責(zé)采集一段短視頻或多幀圖像,并做初步的檢測(比如動作檢測),然后將關(guān)鍵幀/特征點(diǎn)信息或經(jīng)過加密處理的數(shù)據(jù)上傳到后端。
- 后端使用更加復(fù)雜或高精度的活體檢測模型(可以是 Python + PyTorch/TensorFlow 等),對圖像進(jìn)行驗(yàn)證,給出結(jié)果返回前端。
- 同時(shí),后端可做更多安全措施,比如將上傳的視頻或圖像與用戶之前的注冊信息進(jìn)行比對,或使用更豐富的計(jì)算資源進(jìn)行深度檢測。
三、參考實(shí)現(xiàn)思路
以下是一個(gè)在瀏覽器端進(jìn)行基礎(chǔ)活體檢測(動作+關(guān)鍵點(diǎn))并配合后端進(jìn)行高精度驗(yàn)證的思路:
瀏覽器端獲取攝像頭流
- 使用
navigator.mediaDevices.getUserMedia({video: true})
獲取用戶視頻流。 - 用戶授權(quán)攝像頭后,將實(shí)時(shí)畫面在
<video>
或<canvas>
中渲染。
前端人臉關(guān)鍵點(diǎn)跟蹤
- 通過如 face-api.js 或 MediaPipe Face Mesh,實(shí)時(shí)獲取人臉的位置與關(guān)鍵點(diǎn)。
- 對檢測到的人臉進(jìn)行簡單預(yù)處理,如裁剪成只包含臉部的圖像。
動作活體檢測(眨眼、點(diǎn)頭等)
- 向用戶提出隨機(jī)指令,如“請眨眼兩次或左右轉(zhuǎn)頭”等。
- 通過關(guān)鍵點(diǎn)數(shù)據(jù)判斷動作是否在合理的時(shí)間內(nèi)完成,并排除假視頻循環(huán)。
- 若完成預(yù)期動作,則判定通過基礎(chǔ)的“動作檢測”門檻。
后端進(jìn)一步驗(yàn)證(可選)
- 將采集到的若干張關(guān)鍵幀或短視頻片段提交到后端,調(diào)用更復(fù)雜/更精確的活體檢測模型(如基于 CNN 或 Transformer 的模型),進(jìn)行更深層次的驗(yàn)證。
- 后端返回“通過”或“不通過”信息,前端顯示結(jié)果。
安全性處理
- 考慮到活體檢測的安全需求,需采取加密、簽名等方式保證上傳數(shù)據(jù)不被篡改。
- 對模型本身進(jìn)行一定的混淆或部署在后端,以減少被攻擊者逆向或者篡改的可能性。
四、優(yōu)缺點(diǎn)對比
方案 | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|
純前端(JavaScript) | 1. 隱私性較好:所有視頻數(shù)據(jù)都在本地處理 2. 無需后端存儲與計(jì)算資源 | 1. 瀏覽器性能限制,模型大時(shí)推理可能卡頓 2. 安全性依賴客戶端實(shí)現(xiàn),易被攻擊者逆向或模擬 |
前端+后端協(xié)同 | 1. 后端可使用強(qiáng)大的模型和算力 2. 安全性更高,可避免算法被逆向 | 1. 需要傳輸視頻/圖像至后端,需做好數(shù)據(jù)安全 2. 需要建設(shè)后端服務(wù),增加開發(fā)復(fù)雜度 |
下面可以基于Vue 3 + Vite的前端項(xiàng)目構(gòu)建一個(gè)簡單的示例結(jié)構(gòu),用于演示如何在瀏覽器端完成基礎(chǔ)的人臉活體檢測。在此示例中,結(jié)合了 Face-API.js 或 MediaPipe Face Mesh 等方式獲取人臉關(guān)鍵點(diǎn)信息,并進(jìn)行簡單的眨眼檢測或頭部動作檢測。
說明:此示例僅演示項(xiàng)目結(jié)構(gòu)和基本實(shí)現(xiàn)流程,側(cè)重于“如何將活體檢測與 Vue 結(jié)合使用”的思路。實(shí)際生產(chǎn)環(huán)境中,還需增加更多安全性和準(zhǔn)確性策略、可能需要后端配合做高精度識別與風(fēng)控。
一、項(xiàng)目結(jié)構(gòu)示例
下面是一個(gè)示例的文件/目錄結(jié)構(gòu):
vue-liveness-detection ├─ package.json # 項(xiàng)目依賴 & 腳本配置 ├─ vite.config.js # Vite 配置 ├─ README.md # 項(xiàng)目說明文檔 ├─ public/ │ └─ favicon.ico # 網(wǎng)站圖標(biāo) └─ src/ ├─ main.js # 入口文件,創(chuàng)建/掛載 Vue 應(yīng)用 ├─ App.vue # 根組件 ├─ assets/ # 靜態(tài)資源目錄 (CSS / 圖片 / ...) │ └─ styles.css ├─ components/ │ ├─ LivenessCheck.vue # 核心的“活體檢測”組件 │ └─ VideoCapture.vue # 攝像頭視頻預(yù)覽組件 ├─ store/ │ └─ index.js # Vuex/Pinia 等狀態(tài)管理(如需) ├─ utils/ │ ├─ faceApi.js # Face-API.js 初始化/工具方法 │ └─ livenessUtils.js # 活體檢測相關(guān)的通用函數(shù) └─ router/ └─ index.js # Vue Router 配置
二、示例代碼
下面給出核心文件的示例代碼。
1. package.json
{ "name": "vue-liveness-detection", "version": "1.0.0", "scripts": { "dev": "vite", "build": "vite build", "serve": "vite preview" }, "dependencies": { "vue": "^3.3.4", "vue-router": "^4.2.2", // 如果需要使用 face-api.js: "face-api.js": "^0.22.2", // 如果使用 pinia 或 vuex: // "pinia": "^2.1.3", // "vuex": "^4.1.0" }, "devDependencies": { "vite": "^4.3.9" } }
2. vite.config.js
import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue()], server: { port: 3000 } })
3. main.js
import { createApp } from 'vue' import App from './App.vue' // 如果需要路由或 Pinia/Vuex,可在此引入 // import router from './router' // import store from './store' import './assets/styles.css' // 自定義全局樣式 createApp(App) // .use(router) // .use(store) .mount('#app')
4. App.vue
<template> <div id="app"> <h1>Vue Liveness Detection Demo</h1> <!-- 在此使用我們的 LivenessCheck 組件 --> <LivenessCheck /> </div> </template> <script> import LivenessCheck from './components/LivenessCheck.vue' export default { name: 'App', components: { LivenessCheck } } </script> <style scoped> #app { padding: 20px; } </style>
5. components/VideoCapture.vue
此組件封裝了獲取攝像頭視頻流的邏輯,并把實(shí)時(shí)視頻流顯示到頁面上。
<template> <div class="video-container"> <video ref="videoRef" autoplay playsinline width="640" height="480" @loadeddata="onVideoLoaded" ></video> </div> </template> <script> export default { name: 'VideoCapture', emits: ['video-ready'], data() { return { stream: null, videoRef: null, } }, mounted() { this.initCamera() }, unmounted() { this.stopCamera() }, methods: { async initCamera() { try { this.stream = await navigator.mediaDevices.getUserMedia({ video: true }) this.videoRef.srcObject = this.stream } catch (err) { console.error('Error accessing camera: ', err) } }, stopCamera() { if (this.stream && this.stream.getTracks) { this.stream.getTracks().forEach(track => track.stop()) } }, onVideoLoaded() { // 通知父組件,視頻可以被處理 this.$emit('video-ready', this.videoRef) } } } </script> <style scoped> .video-container { max-width: 640px; max-height: 480px; border: 1px solid #ccc; display: inline-block; } </style>
6. utils/faceApi.js
使用 face-api.js 進(jìn)行人臉檢測與關(guān)鍵點(diǎn)獲取的初始化邏輯示例:
import * as faceapi from 'face-api.js' // 預(yù)加載模型 export async function loadFaceApiModels() { const MODEL_URL = '/models' // 需要把 model 文件放到 public/models 下 await faceapi.nets.tinyFaceDetector.loadFromUri(MODEL_URL) await faceapi.nets.faceLandmark68Net.loadFromUri(MODEL_URL) // 可選:如果需要識別表情、年齡等,還可加載其他模型 } // 進(jìn)行人臉檢測并獲取 landmarks export async function detectFaceAndLandmarks(videoElement) { // 使用 tinyFaceDetector 做人臉檢測 const detection = await faceapi .detectSingleFace(videoElement, new faceapi.TinyFaceDetectorOptions()) .withFaceLandmarks() return detection // 包含 { detection, landmarks } }
需要將 face-api.js 預(yù)訓(xùn)練模型文件 放在
public/models
目錄下,或在其他路徑中自行指定。
7. components/LivenessCheck.vue
此組件是示例的“活體檢測主邏輯”,會結(jié)合 VideoCapture
組件獲取視頻,并利用 faceApi.js
檢測人臉和關(guān)鍵點(diǎn),進(jìn)行簡單的眨眼或動作檢測。
<template> <div class="liveness-check"> <VideoCapture @video-ready="handleVideoReady" /> <div class="status"> <p>Status: <strong>{{ detectionStatus }}</strong></p> </div> <button @click="startLivenessCheck" :disabled="detectionLoading"> {{ detectionLoading ? '檢測中...' : '開始檢測' }} </button> </div> </template> <script> import VideoCapture from './VideoCapture.vue' import { loadFaceApiModels, detectFaceAndLandmarks } from '@/utils/faceApi.js' export default { name: 'LivenessCheck', components: { VideoCapture }, data() { return { videoElement: null, detectionStatus: '未檢測', detectionLoading: false, checkInterval: null } }, async mounted() { // 加載 faceapi 模型 await loadFaceApiModels() }, beforeUnmount() { if (this.checkInterval) { clearInterval(this.checkInterval) } }, methods: { handleVideoReady(videoRef) { this.videoElement = videoRef }, startLivenessCheck() { if (!this.videoElement) { alert('無法訪問攝像頭視頻,請檢查是否允許權(quán)限') return } this.detectionLoading = true this.detectionStatus = '檢測開始...' // 定時(shí)進(jìn)行人臉檢測 this.checkInterval = setInterval(async () => { const detection = await detectFaceAndLandmarks(this.videoElement) if (!detection) { this.detectionStatus = '未檢測到人臉' return } // 獲取 landmarks const { landmarks } = detection // 簡易眨眼檢測(閾值判定) const leftEye = landmarks.getLeftEye() const rightEye = landmarks.getRightEye() // 計(jì)算眼睛上下邊緣間距:過小可能為閉眼 const leftEyeOpenScore = this.getEyeOpenScore(leftEye) const rightEyeOpenScore = this.getEyeOpenScore(rightEye) if (leftEyeOpenScore < 4 || rightEyeOpenScore < 4) { this.detectionStatus = '檢測到眨眼' } else { this.detectionStatus = '雙眼睜開' } }, 1000) // 每秒檢測一次 }, getEyeOpenScore(eyePoints) { // eyePoints 是 6 個(gè)關(guān)鍵點(diǎn) [ [x1,y1], [x2,y2], ..., [x6,y6] ] // 僅做一個(gè)非常簡化的上下邊緣距離計(jì)算:如 (point[1].y - point[5].y) 的絕對值 // 生產(chǎn)環(huán)境中應(yīng)采用更嚴(yán)謹(jǐn)?shù)膸缀畏椒? if (!eyePoints || eyePoints.length < 6) return 0 const topY = eyePoints[1].y const bottomY = eyePoints[4].y return Math.abs(topY - bottomY) } } } </script> <style scoped> .liveness-check { margin-top: 20px; } .status { margin: 10px 0; } </style>
在實(shí)際中,活體檢測并不僅僅是“眨眼”這么簡單,可能需要結(jié)合隨機(jī)動作指令、面部姿態(tài)估計(jì)、或更高級的深度學(xué)習(xí)模型等多種技術(shù)來提高安全性。
三、代碼運(yùn)行
克隆或下載該示例項(xiàng)目代碼至本地,并安裝依賴:
cd vue-liveness-detection npm install
在 public/models
放置 face-api.js 所需的模型文件(你可以從官方倉庫下載),確保和 faceApi.js
中的 MODEL_URL
對應(yīng)。啟動開發(fā)服務(wù)器:
npm run dev
在瀏覽器中打開 http://localhost:3000,允許使用攝像頭權(quán)限,即可看到示例界面。
四、可能的擴(kuò)展與改進(jìn)
安全挑戰(zhàn)
- 僅眨眼容易被錄制視頻或動畫欺騙,可在前端發(fā)出隨機(jī)指令,如“請上下點(diǎn)頭”、“請張嘴”、“左轉(zhuǎn)頭”、“看向右側(cè)” 等多步動作指令來提高偽造難度。
- 也可使用 MediaPipe Face Mesh 來進(jìn)行更多面部關(guān)鍵點(diǎn)的判斷或 3D 姿態(tài)分析。
深度學(xué)習(xí)模型
- 如果你有更加先進(jìn)的二分類模型 (活體 / 非活體),可使用 TensorFlow.js 或 ONNX Runtime Web 在瀏覽器端加載推理。
- 或者將視頻流片段上傳至后端,用 Python + PyTorch/TensorFlow 做復(fù)雜檢測,提高識別準(zhǔn)確率。
對接后端
- 如需在后端做登錄/注冊流程,可將檢測結(jié)果或視頻流片段上傳后端,結(jié)合用戶認(rèn)證、存儲等邏輯。
最終說明
以上給出的文件/目錄以及示例代碼只是一個(gè)最簡化的演示,用來測試“在 Vue 前端項(xiàng)目中如何集成活體檢測邏輯”。實(shí)際應(yīng)用中,還需要根據(jù)產(chǎn)品需求、用戶隱私與安全性要求以及硬件/網(wǎng)絡(luò)環(huán)境來對檢測策略和架構(gòu)做更深入的定制。
五、總結(jié)
- 可以用 JavaScript 來實(shí)現(xiàn)活體檢測,但若要做到安全、準(zhǔn)確、魯棒,往往需要:
- 使用前端的人臉/關(guān)鍵點(diǎn)檢測庫做實(shí)時(shí)動作檢測,輔助判定是否為翻拍;
- 引入深度學(xué)習(xí)模型(WebAssembly/WebGPU)或借助后端服務(wù)做更深入的活體檢測判斷;
- 結(jié)合多種策略(光照分析、動作挑戰(zhàn)、三維姿態(tài)分析、甚至紅外或結(jié)構(gòu)光信息)來防御常見偽造手段。
- 純 JavaScript + 前端瀏覽器能實(shí)現(xiàn)基礎(chǔ)的人臉活體檢測,一些開源示例也已能初步區(qū)分真人和簡單平面翻拍,但應(yīng)根據(jù)安全需求和使用場景決定是否需要后端協(xié)助,以及更嚴(yán)謹(jǐn)?shù)挠布蛩惴ㄖС帧?/li>
到此這篇關(guān)于JavaScript能否實(shí)現(xiàn)人體面部活體檢測的功能的文章就介紹到這了,更多相關(guān)JavaScript人體面部活體檢測內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript之a(chǎn)ppendChild、insertBefore和insertAfter使用說明
這幾天需要用到對HTML節(jié)點(diǎn)元素的刪/插操作,由于用到insertBefore方法的時(shí)候遇到了一些麻煩,現(xiàn)在作為知識的整理,分別對appendChild、insertBefore和insertAfter做個(gè)總結(jié)2010-12-12javascript Array.prototype.slice的使用示例
javascript Array.prototype.slice除了常見的從某個(gè)數(shù)組中抽取出新的數(shù)組外,它還有一些其他的用法,下面就為大家講這些妙用2013-11-11bootstrap Validator 模態(tài)框、jsp、表單驗(yàn)證 Ajax提交功能
這篇文章主要介紹了bootstrap Validator 模態(tài)框、jsp、表單驗(yàn)證 Ajax提交功能的實(shí)現(xiàn)代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2017-02-02