这个是我通过穆雄雄的博客,稍微的修改和调试,基本能够实现摇摇头,和张张嘴的功能,但是眨眨眼还没办法实现,以及识别时还会有点小问题。
所以记个学习心得。
话不多说,直接上代码

html 部分

<!doctype html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>人脸识别</title>
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<link href="css/mui.min.css" rel="stylesheet" />
		<style>
			body {
				text-align: center;
				background-color: rgba(0, 0, 0, 0~1);
			}
			.contentcss {
				text-align: center;
				margin: 0 auto;
				vertical-align: middle;
				background-color: rgba(0, 0, 0, 0~1)
			}
			
			.headcss {
				border: 1px solid red;
				width: 300px;
				height: 300px;
				background-color: wheat;
				margin: 0 auto;
				border-radius: 50%;
				overflow: hidden;
			}
			
			#style{
				font-size:25px;margin-top:20%;color: #FFFFFF;
			}
			.videocss {
				width: 100%;
				height: 100%;
				border-radius: 50%;
				text-align: center;
			}
		</style>
	</head>

	<body style="background: rgb(2,2,2,0.5);">
		<div class="mui-content contentcss" id="content" style="background: rgb(2,2,2,0);">
			<div class="headcss" id="headdiv">
				<video id="video" class="videocss" autoplay width="300" height="300"></video>
				<canvas style="visibility:hidden;" id="canvas" width="300" height="300"></canvas>
			</div>
			<div id="style">请将头部对准摄像头</div>

			<div id="tip" style="display: none;"></div>
			<input type="hidden" id="result" />
			<div id="msg" style="display: none;"></div>
			<div id="positions"></div>
		</div>
	</body>

	<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
	<script src="js/utils.js"></script>
	<script src="js/numeric.js"></script>
	<script src="js/ccv.js"></script>
	<script src="js/clmtrackr.js"></script>
	<script src="js/model_pca_20_svm.js"></script>

	<script src="js/mui.min.js"></script>
	<script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
	<script type="text/javascript">
		mui.init({
			keyEventBind: {
				backbutton: false //关闭back按键监听
			}
		});


		// 注意本例需要在HTTPS协议网站中运行,新版本Chrome中getUserMedia接口在http下不再支持。
		// 设置事件监听器
		var video, sinterval, pageid;
		var showpos = false;
		video = document.getElementById('video');

		window.addEventListener("DOMContentLoaded", () => {
			//获取屏幕长宽高定义摄像头出现位置
			var width = document.documentElement.clientWidth;
			var height = document.documentElement.clientHeight;
			document.getElementById("content").style.height = (height - 200) + "px";
			document.getElementById("content").style.width = width + "px";
			document.getElementById("headdiv").style.marginTop = (height - 500) / 2 + "px";

			// document.addEventListener('UniAppJSBridgeReady', ()=> {
			// 	sinterval = setInterval(() => {
			// 		// let url = document.getElementById('imgUrl').value
			// 		if(url){
			// 			clearInterval(sinterval)
			// 			uni.postMessage({
			// 				data: {  
			// 					imgUrl: url
			// 				}  
			// 			});  
			// 			uni.navigateBack()
			// 		}
			// 	}, 1000);
			// });		

			var mediaConfig = {
				video: true
			};
			var errBack = function(e) {
				console.log('An error has occurred!', e)
			};
			console.log("start");

			// Put video listeners into place
			if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
				navigator.mediaDevices.getUserMedia(mediaConfig).then(function(stream) {
					// video.src = window.URL.createObjectURL(stream);				
					video.srcObject = stream;
					start(video)
				});
			}
			/* 旧版代码如下! */
			else if (navigator.getUserMedia) { // 标准
				navigator.getUserMedia(mediaConfig, function(stream) {
					video.src = stream;
					start(video)
				}, errBack);
			} else if (navigator.mozGetUserMedia) { // Mozilla-prefixed
				navigator.mozGetUserMedia(mediaConfig, function(stream) {
					video.src = window.URL.createObjectURL(stream);
					start(video)
				}, errBack);
			} else if (navigator.msGetUserMedia) { // Mozilla-prefixed
				navigator.msGetUserMedia(mediaConfig, function(stream) {
					video.src = window.URL.createObjectURL(stream);
					start(video)
				}, errBack);
			} else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
				navigator.webkitGetUserMedia(mediaConfig, function(stream) {
					video.src = window.webkitURL.createObjectURL(stream);
					start(video)
				}, errBack);
			}

		}, false);

		function start(video) {
			video.onloadedmetadata = function(e) {
				video.play();
				setTimeout(() => {
					alive_mouse();
					var audio = document.createElement('audio');
					var source = document.createElement('source');
					source.type = "audio/mp3";
					source.src = "mp3/alive_mouse.mp3";
					source.autoplay = "autoplay";
					source.controls = "controls";
					audio.appendChild(source);
					audio.play();
					startTrack();
				}, 1000)
			};
		}
	</script>
	<script type="text/javascript">
		//活体
		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;
		var last_dm = 0
		var last_dis_header = 0;
		var is_alive_header = false;
		
		var last_eye_x  = 0
		var last_eye_y  = 0
		var last_mouse_x  = 0 
		var last_mouse_y  =0

		//检测张嘴动作
		function alive_mouse() {
			document.getElementById("style").innerHTML = "请张合嘴巴";
			document.getElementById('result').value = "";
			is_mouse_ok = false;
			last_dis_mouse = 0;
			last_time = 0;
			is_alive_mouse = true;
			is_alive_header = false
		}
		//检测摇头动作
		function alive_header() {
			document.getElementById("style").innerHTML = "摇摇头";
			document.getElementById('result').value = "";
			is_header_ok = false;
			last_dis_header = 0;
			last_time = 0;
			is_alive_header = 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');

			function drawLoop() {
				requestAnimationFrame(drawLoop);
				//ctracker.draw(canvasInput );
				var positions = ctracker.getCurrentPosition();
				if (positions) {
					//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 dn = Math.abs(dis_eye_norse - last_dis_eye_norse);
							// console.log(dn)
							//上嘴唇 和下嘴唇距离
							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 dm = Math.abs(dis_mouse - last_dis_mouse);
						
				// console.log ("鼻子左"+Math.abs(positions[62][0]) ,"鼻子左旧"+ last_nose_left,"左差"+Math.abs(positions[62][0] - last_nose_left))
				// console.log ("鼻子上"+Math.abs(positions[62][1] ),"鼻子上旧"+  last_nose_top,"上差"+ Math.abs(positions[62][1] - last_nose_top))
							//鼻子的位置确保变化不大
							if (last_nose_left > 0 && last_nose_top > 0 && Math.abs(positions[62][0] - last_nose_left) < 10 &&
								Math.abs(positions[62][1] - last_nose_top) < 10) {
									// console.log("旧两次距离差"+ Math.floor(last_dm))
									// console.log("两次距离差"+ Math.floor(dm))	
									document.getElementById("style").innerHTML = "请张合嘴巴";
									console.log(dm-last_dm)
								if (Math.floor(dm) >0  && last_dm>0 &&  ( dm-last_dm)>6){
									document.getElementById('result').value = "通过";
									var msg_mouse = document.getElementById('result');
									if (msg_mouse.value == '通过') {
										
										is_alive_mouse = false;
										is_mouse_ok = true;
										//验证摇头
										if (is_mouse_ok) {
											setTimeout(() => {
												alive_header();
												var audio = document.createElement('audio');
												var source = document.createElement('source');
												source.type = "audio/mp3";
												source.src = "mp3/alive_head.mp3";
												source.autoplay = "autoplay";
												source.controls = "controls";
												audio.appendChild(source);
												audio.play();
												startTrack();
												last_nose_left = 0
												last_nose_top = 0
												last_dis_eye_norse = 0
												last_dis_mouse = 0
												last_time = new Date().getTime();
											}, 1000)
										}
									}
								}
								last_dis_mouse = dis_mouse;
								last_dm = dm
							}else {
									document.getElementById("style").innerHTML = "请保持头部不动";
								}

							last_time = new Date().getTime();
							last_dis_eye_norse = dis_eye_norse;
							last_nose_left = positions[62][0];
							last_nose_top = positions[62][1];

						}
					}
					else if(is_alive_header){
						
						if (last_time == 0 || (new Date().getTime() - last_time > 500 && new Date().getTime() - last_time < 10000)) {
							// console.log("鼻子" + Math.abs(positions[27][0] - last_nose_left  ) )
							// console.log("嘴巴" + Math.abs( positions[53][0] - last_mouse_x)  )  	
							// console.log("眼睛" + Math.abs(positions[62][0] - last_eye_x  )  )
						if (last_nose_left >0 && last_nose_top >0  && last_eye_x >0 && last_eye_y >0 &&
							last_mouse_x  > 0 && last_mouse_y >0  &&
							Math.abs(positions[27][0] - last_nose_left  ) > 10 && 
							Math.abs( positions[53][0] - last_mouse_x  ) > 10 &&  
							Math.abs( positions[62][0] - last_eye_x  ) > 10
							){
									document.getElementById("style").innerHTML = "通过";
									cc.drawImage(video, 0, 0, video.width, video.height);
									var dataURL = canvasInput.toDataURL("image/jpeg		", 1.0); //第二个参数是质量
									
									}
							
						// 		last_time = new Date().getTime();
								
								last_nose_left = positions[27][0];
								last_nose_top = positions[27][1];
								last_eye_x =  positions[62][0];
								last_eye_y = positions[62][1];
								last_mouse_x =  positions[53][0] ;
								last_mouse_y =  positions[53][1];
								
						}
						
					}

				}

				// requestAnimationFrame(drawLoop);

			}

			drawLoop();

		}
		startTrack()
	</script>
</html>

源码传送门
提取码:vtee

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐