定制开发微信小程序人脸识别功能(wx.faceDetect)、带扫脸动画、人脸图片获取(upng.js)及位置展示

目录

1. 定制开发微信小程序

定制开发方案已废弃: 定制开发用到的第三方框架: (速度太慢,容易卡顿)
推荐使用:

1. 定制开发初始化人脸识别

	wx.initFaceDetect()
  • 1

2. 创建 camera 上下文 CameraContext 对象

	this.cameraEngine = wx.createCameraContext();
  • 1

3.获取 Camera 定制开发实时帧数据

	const listener = this.cameraEngine.onCameraFrame()
  • 1

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

	wx.faceDetect()
  • 1

5.完整代码

<template>	<view>		<view class="d-flex justify-content-between align-items-center update-box mt-40 mr-32">			<!-- 可用iconfont -->			<image @click="devicePosition=!devicePosition" class="camera-change-image" mode="widthFix"				src="@/static/images/camera_change.png"></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 mt-40" v-show="!tempImg && 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>		</view>	</view></template><script>	import upng from "@/common/js/upng.js"	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			}		},		onShow: function() {			this.isVerify = false;			this.tipsText = "";			this.isFlag = true;		},		onLoad(options) {			this.origin = options.origin;			this.initData();			this.lineAnimation()		},		onUnload: function() {			clearInterval(this.timer);			this.timer = null;			this.isFlag = false;		},		methods: {			// 初始化相机引擎			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.tempImg) {						return;					}					// 4、人脸识别,使用前需要通过 wx.initFaceDetect 进行一次初始化,推荐使用相机接口返回的帧数据					wx.faceDetect({						frameBuffer: frame.data,						width: frame.width,						height: frame.height,						enablePoint: true,						enableConf: true,						enableAngle: true,						enableMultiFace: true,						success: (faceData) => {							if (this.isVerify) return							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 {									this.tipsText = '校验中...'									this.isVerify = true;																		// 太快获取的人脸可能比较抽象,给用户一个准备时间									setTimeout(() => {										//借助upng把流转为二进制数据										let pngData = upng.encode([frame.data], frame.width,												frame.height),											base64 = arrayBufferToBase64(pngData);																					// 获取到base64后可以已上传,展示,或保存到本地																				var imageType = getImageType();										function getImageType() {											let type = "center"											if (face.y / frame.height < 0.3333) {												type = "top"											} else if (face.y / frame.height > 0.6666) {												type = "bottom"											}											return type;										}										//二进制转base64										function arrayBufferToBase64(buffer) {											var binary = '';											var bytes = new Uint8Array(buffer);											var len = bytes.byteLength;											for (var i = 0; i < len; i++) {												// unicode编码还原												binary += String.fromCharCode(bytes[i]);											}											return "data:image/png;base64," + btoa(binary);										}										// 小程序没有window对象,需手动实现btoa()方法										// 作用: 字符转base64										function btoa(string) {											const b64 =												"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="											string = String(string);											var bitmap, a, b, c,												result = "",												i = 0,												rest = string.length %												3; // To determine the final padding											for (; i < string.length;) {												if ((a = string.charCodeAt(i++)) > 255 ||													(b = string.charCodeAt(i++)) > 255 ||													(c = string.charCodeAt(i++)) > 255)													throw new TypeError(														"Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range."													);												bitmap = (a << 16) | (b << 8) | c;												result += b64.charAt(bitmap >> 18 & 63) + b64													.charAt(bitmap >> 12 & 63) +													b64.charAt(bitmap >> 6 & 63) + b64.charAt(														bitmap & 63);											}											return rest ? result.slice(0, rest - 3) + "==="												.substring(rest) : result;										};										this.tipsText = '校验成功'										setTimeout(() => {											this.clickPushDetail(imageType);										}, 50)									}, 300)								}							}						},						fail: (err) => {							if (this.isVerify) return							if (err.x == -1 || err.y == -1) {								this.tipsText = '检测不到人'							} else {								this.tipsText = err.errMsg || '网络错误,请退出页面重试'							}						},					})				})				// 5、开始监听帧数据				listener.start()				// #endif			},			clickPushDetail(imageType) {				if (!this.isFlag) return				// 可以跳转到详情页面			},			lineAnimation() {				if (this.timer) return				this.timer = setInterval(() => {					this.translateY += 3;					if (this.translateY >= 460) {						this.translateY = 10;					}				}, 12)			},		}	}</script><style>	page {		background-color: #000000;	}</style><style lang="scss" scoped>	.d-flex {	  display: flex;	}		.justify-content-center {	  justify-content: center;	}		.align-items-center {	  align-items: center;	}			.camera-change-image {		width: 48rpx;		margin-left: 40rpx;	}		.mr-32{		margin-right: 32rpx;	}		.mt-40 {	  margin-top: 40rpx;	}		.text-center {	  text-align: center;	}		.position-relative{		position: relative;	}		.w-100{		width: 100%;	}	.update-box {		color: #ffffff;	}	.head-image-box {		position: absolute;		top: 10vh;		color: white;		.camera {			width: 100%;			height: 872rpx;		}		.title {			font-size: 48rpx;			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;			// transform: translateY(-24rpx);			// animation: radar-beam 1.5s infinite;			// background: linear-gradient(180deg, rgba(13, 110, 217, 0) 0%, rgba(13, 110, 217, 0.4000) 100%);			z-index: 2;		}		// @keyframes radar-beam {		// 	0% {		// 		transform: translateY(24rpx);		// 	}		// 	100% {		// 		transform: translateY(450rpx);		// 	}		// }	}</style>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318

附带的圆角图片真机展示问题

父元素添加:-webkit-backface-visibility: hidden;
-webkit-transform: translate3d(0, 0, 0);

.image-box {				overflow: hidden;				border-radius: 50%;				-webkit-backface-visibility: hidden;				-webkit-transform: translate3d(0, 0, 0);				z-index: 1;				.face-image {					width: 100%;					height: 100%;					position: absolute;					left: 0;					&.top {						top: 0;					}					&.bottom {						bottom: 0;					}					&.center {						top: 50%;						transform: translateY(-50%);					}				}			}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

借鉴于:

2. H5人脸识别

详见:

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发