目录
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人脸识别
详见: