人脸识别H5页面(打开指定摄像头navigator,绘制人脸框tracking.js)

参考代码1

导入两js文件

前端人脸识别框架:https://trackingjs.com
下载zip包获取里面的 face.min.js 及 tracking-min.js
解压后仔细找找

<script src="./js/tracking-min.js"></script>
<script src="./js/face-min.js"></script>
下面代码中有注释可以看看。
代码1:是人脸的H5页面,需要引入上门提到的两个js文件。
代码2:切换摄像头的的一个实例,表达的意思就是先获取所有摄像的设备id,再通过设备id打开对应的摄像头。

	<style>
		#video_bind,
		#canvas_bind {
			width: 375rem;
			height: 486rem;
			object-fit: cover;
		}


		#canvas_bind {
			position: absolute;
			top: 0;
			z-index: 2;
			/* z-index: -1; */
		}

		.tip-box {
			margin-top: 32rem;
			font-size: 24rem;
		}
	</style>
	<div>
		<video width="375" height="486" id="video_bind" autoplay playsinline webkit-playsinline="true">

		</video>
		<div class="tip-box text-center"></div>
		<canvas id="canvas_bind"></canvas>
	</div>

	<script src="./js/tracking-min.js"></script>
	<script src="./js/face-min.js"></script>
	<script type="text/javascript">
		var tipFlag = false // 是否检测
		var faceflag = false // 是否进行拍照
		var informationTitle = document.querySelector(".tip-box") //人脸提示
		// 获取video、canvas实例
		var facevideo = document.getElementById('video_bind');
		var facecanvas = document.getElementById('canvas_bind');
		facecanvas.width = facecanvas.clientWidth;
		facecanvas.height = facecanvas.clientHeight;
		
		var videoWidth = videoHeight = 0
		facevideo.addEventListener('canplay', function() {
			videoWidth = this.videoWidth;
			videoHeight = this.videoHeight;
		});

		var facecontext = facecanvas.getContext('2d');
		var tracker = new tracking.ObjectTracker('face');
		// 每次打开弹框先清除canvas没拍的照片
		facecontext.clearRect(0, 0, facecanvas.width, facecanvas.height);

		if (navigator.mediaDevices === undefined) {
			navigator.mediaDevices = {}
		}
		if (navigator.mediaDevices.getUserMedia === undefined) {
			navigator.mediaDevices.getUserMedia = function(constraints) {
				var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
				if (!getUserMedia) {
					return Promise.reject(new Error("getUserMedia is not implemented in this browser"));
				}
				return new Promise(function(resolve, reject) {
					getUserMedia.call(navigator, constraints, resolve, reject);
				})
			}
		}

		navigator.mediaDevices.getUserMedia({
			audio: false,
			//打开摄像头方法1:
			video: {
				facingMode: "environment"
			}

		//打开摄像头方法2:
	//	video: {
      //      deviceId: 		"77604ab12bb8b7cf337c4069da4e701d3786adb8a4115436d0aef1792175c289"}

		}).then(function(stream) {
			// 使用监听人脸的包
			tracker.setInitialScale(4);
			tracker.setStepSize(2);
			tracker.setEdgesDensity(0.1);

			//打开摄像头方法1(这里有个问题,非手机端他只会打开默认的摄像头)
			var tra = tracking.track('#video_bind', tracker, {
				camera: true
			});
			
			//打开摄像头方法2:(上面的video要改,参数哪里来,看代码参考2)
		// facevideo.srcObject = stream;
       // facevideo.play();
      //  var tra = tracking.track('#video_bind', tracker);



			var timer = null;
			// 创建监听 每帧都会触发
			tracker.on('track', function(event) {
				if (!tipFlag) {
					facecontext.clearRect(0, 0, facecanvas.width, facecanvas.height);
					if (event.data.length === 0) {
						//未检测到人脸
						if (!faceflag && !timer) {
							timer = setTimeout(() => {
								informationTitle.innerHTML = '未检测到人脸'
							}, 500)
						}
					} else if (event.data.length === 1) { // 长度为多少代表检测到几张人脸
						window.clearTimeout(timer);
						timer = null;
						informationTitle.innerHTML = '请将脸部置于屏幕中央';
						//检测到一张人脸
						if (!tipFlag) {
							// 给检测到的人脸绘制矩形
							event.data.forEach(function(rect) {
								facecontext.strokeStyle = '#a64ceb';
								facecontext.strokeRect(rect.x, rect.y, rect.width, rect.height);
							});
							let rect = event.data[0];
							//判断脸部是否在屏幕中间
							if (!faceflag && rect.x > facevideo.clientWidth * 0.3 && rect.x < facevideo
								.clientWidth * 0.7) { // 检测到人脸进行拍照,延迟0.5秒
								informationTitle.innerHTML = '识别中,请勿乱动~';
								faceflag = true;
								tipFlag = true;
								setTimeout(() => {
									tackPhoto() // 拍照
								}, 500);
							}

						}
					} else {
						//检测到多张人脸
						if (!faceflag) {
							informationTitle.innerHTML = '只可一人进行人脸识别!'
						}
					}
				}
			});

			function tackPhoto() {
				// 为什么调用getObjectFitSize,因为摄像头获取的图片和绘制的图片大小和区域可能不一致
				// 所以需要把人脸置于屏幕中间,绘制中间部分图片,如果不需要直接调用第二种方式	
				const {
					sx,
					sy,
					swidth,
					sheight,
					x,
					y,
					width,
					height
				} = getObjectFitSize('cover', facevideo.clientWidth, facevideo.clientHeight, videoWidth, videoHeight)
				facecontext.drawImage(facevideo, sx, sy, swidth, sheight, x, y, width, height);
				// 第二种方式	
				// facecontext.drawImage(facevideo, 0, 0, facevideo.clientWidth, facevideo.clientHeight);
				var snapData = facecanvas.toDataURL('image/png');
				var imgSrc = "data:image/png;" + snapData;
				// document.querySelector("img").src = imgSrc;

				sessionStorage.setItem("faceImage", imgSrc);
				// history.go(-1);
				history.back()
				facevideo.srcObject.getTracks().forEach(track => track.stop());
				// 取消监听
				tra.stop();
			}

		}).catch(function(err) {
			informationTitle.innerHTML = '打开摄像头失败'
		})

		/**
		 * 计算图片裁剪或者摆放位置
		 * @param {*} type  contain, cover 暂时只兼容这两个模式
		 * @param {*} containerWidth  容器宽度
		 * @param {*} containerHeight  容器高度
		 * @param {*} imgWidth   图片宽度
		 * @param {*} imgHeight  图片高度
		 * @return {*} canvas drawImage的所有入参
		 */
		function getObjectFitSize(
			type = "cover",
			containerWidth,
			containerHeight,
			imgWidth,
			imgHeight
		) {
			let radio = 1, // 容器与图片的比例
				sx = 0, // 开始剪切的 x 坐标位置。
				sy = 0, // 开始剪切的 y 坐标位置。
				swidth = imgWidth, // 被剪切图像的宽度。
				sheight = imgHeight, // 被剪切图像的高度。
				x = 0, // 在画布上放置图像的 x 坐标位置。
				y = 0, // 在画布上放置图像的 y 坐标位置。
				width = containerWidth, // 要使用的图像的宽度(伸展或缩小图像)。
				height = containerHeight; // 要使用的图像的高度(伸展或缩小图像)。
			let cWHRatio = containerWidth / containerHeight;
			let iWHRatio = imgWidth / imgHeight;
			if (type === "cover") {
				// cover模式,需要裁剪
				if (iWHRatio >= cWHRatio) {
					// 横图,高先匹配,裁剪宽度
					radio = containerHeight / imgHeight;
					sx = (imgWidth - containerWidth / radio) / 2;
					swidth = containerWidth / radio;
					sheight = imgHeight;
				} else {
					// 竖图,宽先匹配,裁剪高度
					radio = containerWidth / imgWidth;
					sy = (imgHeight - containerHeight / radio) / 2;
					swidth = imgWidth;
					sheight = containerHeight / radio;
				}
			} else if (type === "contain") {
				if (iWHRatio >= cWHRatio) {
					// 横图,宽先匹配,高度自适应
					radio = containerWidth / imgWidth;
					y = (containerHeight - imgHeight * radio) / 2;
					height = imgHeight * radio;
				} else {
					// 竖图,高先匹配,宽度自适应
					radio = containerHeight / imgHeight;
					x = (containerWidth - imgWidth * radio) / 2;
					width = imgWidth * radio;
				}
			}
			return {
				sx,
				sy,
				swidth,
				sheight,
				x,
				y,
				width,
				height,
			};
		}
	</script>

参考代码2:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>web获取设置和切换摄像头</title>
		<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
	</head>
	<body>
		<div id="container-video">
			<video id="video" width="500" height="300" autoplay></video>
			<br>
			<select id="video-all"></select>
			<br>
			<button id="snap">摄像头照相功能</button>
			<br>
			<canvas id="canvas" width="500" height="300"></canvas>
		</div>
		<script type="text/javascript">
			window.onload = () => {
				cameraSwitchApply();
			}
			/**
			 * 【摄像头默认使用】或【摄像头切换使用】
			 */
			function cameraSwitchApply(){
				var canvas = document.getElementById("canvas");
				var context = canvas.getContext("2d");
				var Mvideo = document.getElementById("video");
				var videoAll = document.getElementById("video-all");
				
				//获取摄像头的名称和设备id 
				//select中设置摄像头选项
				let VideoAllInfo=[];
				navigator.mediaDevices.enumerateDevices().then((devices) => {
					if(devices){
						console.info(devices);
						 devices.forEach((value,index)=>{
							  /**
							 //kind: "videoinput";指的是摄像头输入设备。
							 //kind: "audiooutput"麦克风或笔记本自身的麦克风输入设备。
							 //kind: "audioinput" 麦克风或笔记本自身的麦克风输入设备。
							  * {
								"deviceId":"d31e8fcdf03bd590df66d4cdef290e71431e3c8acc5e617948be13b6de35844a",
								"kind":"videoinput",
								"label":"Logitech HD Webcam C270 (046d:0825)",
								"groupId":"7fb1407dbd9602f5e481567380a9fa9c360898f2de42be1abb0d201c75dea18f"
								},
							  */
							 if(value.kind=="videoinput"){
								 VideoAllInfo.push(value);
							 }
						 });
						if(VideoAllInfo.length>0){
							let videoAllItem="";
							VideoAllInfo.forEach((value,index)=>{
								let ItemDom=`<option value="${value.deviceId}">${value.label}</option>`
								videoAllItem += ItemDom;						
							});
							videoAll.innerHTML = videoAllItem;
						}
					}	
				});
				
				 //监听select的改变:切换摄像头
				document.getElementById("video-all").onchange = () => {
					if (document.getElementById("video-all").children.length > 0) {
						let selIndex = document.getElementById("video-all").selectedIndex; // //获取当前选择的选项的index值
						let selectedValue = document.getElementById("video-all").options[selIndex].value; //获取选中的value值
						let selectedText = document.getElementById("video-all").options[selIndex].innerText; //获取选中的内容   
						console.log(selectedValue,selectedText);
						//切换摄像头
						setCatchVideo(Mvideo,selectedValue);
					};
				}
				//设置默认摄像头
				setCatchVideo(Mvideo,"");
				//摄像头照相功能
				document.getElementById("snap").onclick = () => {
					context.drawImage(Mvideo, 0, 0, 500, 300);
				}
			}
			
			/**
			 * 设置摄像头和切换摄像头
			 * @param {Object} videoDom  摄像头对象
			 * @param {Object} videoID   摄像头deviceId
			 */
			function setCatchVideo(videoDom,videoID){
				let videoObj;
				if(videoID==""){
					//设置默认获取的摄像头
					videoObj = {
						"video": true
					}
				}else{
					//切换摄像头
					videoObj = {
						"video": { deviceId: videoID},
					};
				}	
				let errBack = function(error) {
					console.log("视频捕获错误: ", error.code,error);
				};
				if (navigator.getUserMedia) { //正常的情况下
					navigator.getUserMedia(videoObj, (stream)=> {
						videoDom.srcObject = stream;
						videoDom.play();
					}, errBack);
				} else if (navigator.webkitGetUserMedia) { // WebKit
					navigator.webkitGetUserMedia(videoObj,  (stream)=> {
						videoDom.src = window.webkitURL.createObjectURL(stream);
						videoDom.play();
					}, errBack);
				} else if (navigator.mozGetUserMedia) { // Firefox
					navigator.mozGetUserMedia(videoObj,  (stream)=> {
						videoDom.src = window.URL.createObjectURL(stream);
						videoDom.play();
					}, errBack);
				};
			}
			
		</script>


	</body>
</html>







  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要实现调用摄像头进行人脸识别,可以使用WebRTC技术,它是一种支持浏览器之间实时通信的开放标准。在这个过程中,需要使用到一些JavaScript库,如Face-api.js和TensorFlow.js等。 在使用Face-api.js进行人脸识别时,可以通过检测关键点的位置来判断眨眼、张嘴或摇头等动作。比如,检测眨眼时可以根据眼睛关键点的位置变化来计算眼睛的开合程度,当眼睛开合程度超过一定阈值时就可以判断为眨眼。 以下是一个简单的示例代码,用于检测眨眼动作: ```javascript const video = document.getElementById("video"); Promise.all([ faceapi.nets.tinyFaceDetector.loadFromUri("/models"), faceapi.nets.faceLandmark68Net.loadFromUri("/models"), faceapi.nets.faceRecognitionNet.loadFromUri("/models"), faceapi.nets.faceExpressionNet.loadFromUri("/models") ]).then(startVideo); function startVideo() { navigator.getUserMedia( { video: {} }, stream => video.srcObject = stream, err => console.error(err) ) } video.addEventListener('play', () => { const canvas = faceapi.createCanvasFromMedia(video); document.body.append(canvas); const displaySize = { width: video.width, height: video.height }; faceapi.matchDimensions(canvas, displaySize); setInterval(async () => { const detections = await faceapi.detectAllFaces(video, new faceapi.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceExpressions(); const resizedDetections = faceapi.resizeResults(detections, displaySize); canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height); faceapi.draw.drawDetections(canvas, resizedDetections); faceapi.draw.drawFaceLandmarks(canvas, resizedDetections); const leftEye = resizedDetections[0].landmarks.getLeftEye(); const rightEye = resizedDetections[0].landmarks.getRightEye(); const eyeAspectRatio = (faceapi.euclideanDistance(leftEye[1], leftEye[5]) + faceapi.euclideanDistance(leftEye[2], leftEye[4])) / (2 * faceapi.euclideanDistance(leftEye[0], leftEye[3])); if (eyeAspectRatio < 0.2) { console.log("Blink detected!"); } }, 100); }); ``` 在上述代码中,我们使用了Face-api.js库来进行人脸识别。首先,我们加载了必要的模型文件,然后通过调用`startVideo`函数来启动摄像头。在视频播放时,我们使用`detectAllFaces`函数来检测视频中出现的所有人脸,并计算出每个人脸的关键点。然后,我们根据左右眼的关键点位置计算出眼睛的开合程度,当开合程度小于一定阈值时,就可以判断为眨眼动作。 类似地,检测张嘴或摇头动作也可以使用类似的方法,通过计算关键点位置的变化来判断。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值