• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

微信小程序人脸识别/采集改进版wx.faceDetect-支持人脸心位置校验,人脸图片采集速度更快,人脸搜索

武飞扬头像
thj13896076523
帮助1

1. 微信小程序人脸识别

1. 初始化人脸识别

	wx.initFaceDetect()

2. 创建 camera 上下文 CameraContext 对象

	this.cameraEngine = wx.createCameraContext();

3.获取 Camera 实时帧数据

	const listener = this.cameraEngine.onCameraFrame()

4.人脸识别,使用前需要通过 wx.initFaceDetect 进行一次初始化,推荐使用相机接口返回的帧数据

	wx.faceDetect()

5.校验人脸是否居中(可调整或注释)

	var centerWidth = 250; //中心位置宽度
	var centerHeight = 250; //中心位置高度
									
	if (face.x > (frame.width - centerWidth) / 2 && face.x < (frame.width - centerWidth) / 2   centerWidth && face.y > (frame.height - centerHeight) / 2 && face.y < (frame.height -centerHeight) / 2   centerHeight) {
			this.tipsText = '校验中...'
			this.isVerify = true;
			// 太快获取的人脸可能比较抽象,给用户一个准备时间
			// setTimeout(async () => {
			this.base64 = await this.changeDataToBase64(frame);
			this.searchUserFace();
			// }, 300)
			} else {
				this.tipsText = '请将人脸对准中心位置'
			}

6. 把满足条件的当前帧数据转为base64(通过canvas转换临时文件在转换为base64只需要1秒不到,比使用upng.js及pako.js的形式快很多(3-7秒),而且upng.js在部分机型容易卡死)

	changeDataToBase64(frame) {
				return new Promise((resolve, reject) => {
					var data = new Uint8Array(frame.data);
					var clamped = new Uint8ClampedArray(data);
					let that = this;
					// 当前帧数据转为data并画在canvas上
					wx.canvasPutImageData({
						canvasId: 'myCanvas',
						x: 0,
						y: 0,
						width: frame.width,
						height: frame.height,
						data: clamped,
						success(res) { 
							// 转换临时文件
							wx.canvasToTempFilePath({
								x: 0,
								y: 0,
								width: frame.width,
								height: frame.height,
								canvasId: 'myCanvas',
								fileType: 'jpg',
								destWidth: frame.width,
								destHeight: frame.height, // 精度修改  
								quality: 0.5,
								success(res) {
									// 临时文件转base64
									wx.getFileSystemManager().readFile({
										filePath: res.tempFilePath, //选择图片返回的相对路径 
										encoding: 'base64', //编码格式  
										success: res => {
											// 保存base64
											resolve(res.data);
										}
									})
								},
								fail(res) {
									reject(false);
								}
							});
						},
						fail(error) {
							console.log(error);
						}
					})
				})
			},
学新通

7. 接入腾讯云第三方人脸识别 -人员管理及人脸搜索功能(每月免费10000次就很润)

完整代码

<template>
	<view>
		<view class="d-flex justify-content-between align-items-center update-box mt-40 mr-32">
			<!-- 镜头翻转 -->
			<image @click="devicePosition=!devicePosition" class="camera-change-image" mode="widthFix"
				src="@/static/images/camera_change.png"></image>
			<!-- 扫二维码 -->
			<image @click="clickScanCode()" class="scan-image" src="@/static/images/face_scan.png" mode="aspectFit">
			</image>
		</view>
		<view class="head-image-box w-100 text-center position-relative">
			<!-- resolution:获取人脸图片后的清晰度 low:低 -->
			<camera v-if='isAuthCamera' :device-position="devicePosition ?'back': 'front'" class="camera" flash="off"
				resolution='low' />
			<view class="title" v-show="tipsText">{{ tipsText }}</view>
			<cover-view class="cover-box" v-show="isShow">
				<cover-image class="image-box" src="@/static/images/camera_verify.png"></cover-image>

				<!-- cover-view 不支持动画所以只能变通的形式实现 -->
				<cover-image :style="'transform: translateY(' translateY 'rpx);'" class="line"
					src="@/static/images/bg_line.png"></cover-image>
				<!-- <cover-view class="line"></cover-view> -->
			</cover-view>
			<canvas id="myCanvas" canvas-id="myCanvas"
				:style="'width:' screenWidth 'px;' 'height:' screenHeight 'px'"></canvas>
		</view>
	</view>
</template>
<script>
	export default {
		name: 'index',
		data() {
			return {
				isShow: false,
				tipsText: '', // 错误文案提示
				tempImg: '', // 本地图片路径
				cameraEngine: null, // 相机引擎
				devicePosition: true, // 摄像头朝向
				isAuthCamera: true, // 是否拥有相机权限
				isVerify: false,
				translateY: -24,
				timer: null,
				isFlag: true,
				origin: null,
				base64: "",
				personId: "",
				isFlag2: true,
				screenWidth: 375,
				screenHeight: 640
			}
		},

		onShow: function() {
			this.isVerify = false;
			this.tipsText = "";
			this.isFlag = true;
			this.lineAnimation();
		},
		onLoad(options) {
			this.initData();
		},
		onUnload() {
			this.clearTimer();
		},
		onHide() {
			this.clearTimer();
		},
		methods: {
			clearTimer(){
				if (this.timer) {
					clearInterval(this.timer);
					this.timer = null;
				}
				this.isFlag = false;
			},
			// 初始化相机引擎
			initData() {
				// #ifdef MP-WEIXIN
				// 1、初始化人脸识别
				wx.initFaceDetect();
				// 2、创建 camera 上下文 CameraContext 对象
				this.cameraEngine = wx.createCameraContext();
				this.isShow = true;

				// 3、获取 Camera 实时帧数据
				const listener = this.cameraEngine.onCameraFrame((frame) => {
					if (this.isVerify) return
					
					//动态设置canvas的宽高,不设置会导致部分机型人脸不完整导致不能识别-----很重要!很重要!很重要!
					if (this.isFlag2) {
						this.isFlag2 = false;
						this.screenWidth = frame.width;
						this.screenHeight = frame.height;
					}
					// 4、人脸识别,使用前需要通过 wx.initFaceDetect 进行一次初始化,推荐使用相机接口返回的帧数据
					wx.faceDetect({
						frameBuffer: frame.data,
						width: frame.width,
						height: frame.height,
						enablePoint: true,
						enableConf: true,
						enableAngle: true,
						enableMultiFace: true,
						success: async (faceData) => {
							let face = faceData.faceInfo[0]
							if (face.x == -1 || face.y == -1) {
								this.tipsText = '检测不到人'
							}
							if (faceData.faceInfo.length > 1) {
								this.tipsText = '请保证只有一个人'
							} else {
								const {
									pitch,
									roll,
									yaw
								} = face.angleArray;
								const standard = 0.5
								if (Math.abs(pitch) >= standard || Math.abs(roll) >= standard ||
									Math.abs(yaw) >= standard) {
									this.tipsText = '请平视摄像头'
								} else if (face.confArray.global <= 0.8 || face.confArray.leftEye <=
									0.8 || face.confArray.mouth <= 0.8 || face.confArray.nose <= 0.8 ||
									face.confArray.rightEye <= 0.8) {
									this.tipsText = '请勿遮挡五官'
								} else {
									if (this.isVerify) return
									//人脸位置校验
									var centerWidth = 250;
									var centerHeight = 250;
									if (face.x > (frame.width - centerWidth) / 2 && face.x < (frame
											.width - centerWidth) / 2   centerWidth && face.y > (frame
											.height - centerHeight) / 2 && face.y < (frame.height -
											centerHeight) / 2   centerHeight) {
										this.tipsText = '校验中...'
										this.isVerify = true;
										// 太快获取的人脸可能比较抽象,给用户一个准备时间
										// setTimeout(async () => {
										this.base64 = await this.changeDataToBase64(
											frame);
										this.searchUserFace();
										// }, 300)
									} else {
										this.tipsText = '请将人脸对准中心位置'
									}

								}
							}
						},
						fail: (err) => {
							if (this.isVerify) return
							if (err.x == -1 || err.y == -1) {
								this.tipsText = '检测不到人'
							} else {
								this.tipsText = err.errMsg || '网络错误,请退出页面重试'
							}
						},
					})
				})
				// 5、开始监听帧数据
				listener.start()
				// #endif
			},

			clickScanCode() {
				// 只允许通过相机扫码
				// #ifdef MP-WEIXIN
				uni.scanCode({
					onlyFromCamera: true,
					success: (res) => {
						var data = JSON.parse(res.result.replace(/\ufeff/g, ""));
						
					}
				});
				// #endif
			},
			changeDataToBase64(frame) {
				return new Promise((resolve, reject) => {
					var data = new Uint8Array(frame.data);
					var clamped = new Uint8ClampedArray(data);
					let that = this;
					var width = this.screenWidth;
					var height = frame.height * this.screenWidth / frame.width;

					wx.canvasPutImageData({
						canvasId: 'myCanvas',
						x: 0,
						y: 0,
						width: frame.width,
						height: frame.height,
						data: clamped,
						success(res) { // 转换临时文件

							wx.canvasToTempFilePath({
								x: 0,
								y: 0,
								width: width,
								height: height,
								canvasId: 'myCanvas',
								fileType: 'jpg',
								destWidth: width,
								destHeight: height, // 精度修改  
								quality: 0.5,
								success(res) {
									// 临时文件转base64
									uni.getFileSystemManager().readFile({
										filePath: res.tempFilePath, //选择图片返回的相对路径 
										encoding: 'base64', //编码格式  
										success: res => {
											// 保存base64
											resolve(res.data);
										}
									})
								},
								fail(res) {
									reject(false);
								}
							});
						},
						fail(error) {
							console.log(error);
						}
					})
				})
			},
			
			searchUserFace() {
				// 1.人脸识别错误 把isVerify设置为true继续识别
				// 2.人脸识别成功,做对应的逻辑
				
				// var params = {
				// 	faceImage: this.base64,
				// 	
				// }
				// searchFaces(params).then(res => {
				// 	if (res.code == 200) {
				//		wx.stopFaceDetect();     //关闭人脸识别
				//		this.listener.stop();    //关闭camera摄像头监听
				// 		this.clickPushDetail(res.data.personCode);
				// 		this.tipsText = '校验成功'
				// 	}
				// }).catch(error => {
				// 	setTimeout(() => {
				// 		this.isVerify = false;
				// 	}, 500)
				// 	this.tipsText = '暂未查找到相关人员'
				// })
			},
			clickPushDetail() {
				// 跳转到其他页面
			},

			lineAnimation() {
				if (this.timer) return
				this.timer = setInterval(() => {
					this.translateY  = 8;
					if (this.translateY >= 460) {
						this.translateY = 10;
					}
				}, 40)
			},
		}
	}
</script>

<style>
	page {
		background-color: #000000;
	}
</style>
<style lang="scss" scoped>
	.camera-change-image {
		width: 52rpx;
		margin-left: 40rpx;
		// margin-top: 24rpx;
	}

	.scan-image {
		width: 48rpx;
	}

	.update-box {
		color: #ffffff;
	}

	.operation-box {
		position: fixed;
		width: 100%;
		bottom: calc(120rpx   env(safe-area-inset-bottom));
		// font-size: 32rpx;

		.icon-box {
			width: 76rpx;
			height: 76rpx;

			&.first {
				width: 72rpx;
				height: 72rpx;
			}
		}


	}

	.head-image-box {
		position: absolute;
		top: 10vh;
		color: white;

		.camera {
			width: 750rpx;
			height: 872rpx;
			position: relative;
			z-index: 10;
		}

		#myCanvas {
			position: absolute;
			z-index: 1;
			top: -10000px;
		}

		.title {
			font-size: 40rpx;
			margin-top: 60rpx;
			// font-weight: bold;
		}

		.cover-box {
			position: absolute;
			top: 40%;
			left: 50%;
			transform: translate(-50%, -50%);
			width: 500rpx;
			height: 500rpx;
		}

		.image-box {
			width: 100%;
			height: 100%;
		}

		.line {
			position: absolute;
			top: 0rpx;
			left: 8rpx;
			right: 8rpx;
			width: auto;
			height: 30rpx;
			z-index: 2;
		}
	}
</style>
学新通

2. H5人脸识别

详见:h5人脸识别

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfihbhg
系列文章
更多 icon
同类精品
更多 icon
继续加载