IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 微信小程序人脸识别/采集改进版-支持人脸中心位置校验,人脸图片采集(速度更快),人脸搜索 -> 正文阅读

[移动开发]微信小程序人脸识别/采集改进版-支持人脸中心位置校验,人脸图片采集(速度更快),人脸搜索

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 {
									//人脸位置校验
									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() {
				// 对接人脸识别接口,做对应的逻辑处理
				// var params = {
				// 	faceImage: this.base64,
				// 	
				// }
				// searchFaces(params).then(res => {
				// 	if (res.code == 200) {
				// 		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>

借鉴于:ZegTsai

2. H5人脸识别

详见:h5人脸识别

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:39:30  更:2022-11-05 00:40:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 18:33:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码