小程序人脸识别—检测人脸图片获取图片

wxml

javascript 复制代码
<view>
  <view class="flex white">
    <!-- 镜头翻转 -->
    <view bindtap="reverse">镜头翻转</view>
    <view bindtap="clickScanCode">扫二维码</view>
  </view>
  <view class="head-image-box w-100 text-center position-relative">
    <!-- resolution:获取人脸图片后的清晰度 low:低 -->
    <camera device-position="{{devicePosition ?'back': 'front'}}" class="camera" flash="off" resolution='low' />
    <view class="title">{{ tipsText }}1</view>
    <image src="{{faceImage}}" mode="" />
    <cover-view class="cover-box" wx:if="{{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>

js

javascript 复制代码
// pages/face/index.js
Page({

  /**
   * 页面的初始数据
   */
  data() {
    return {
      isShow: false,
      tipsText: '', // 错误文案提示
      tempImg: '', // 本地图片路径
      cameraEngine: null, // 相机引擎
      devicePosition: false, // 摄像头朝向
      isAuthCamera: true, // 是否拥有相机权限
      isVerify: false,
      translateY: -24,
      timer: null,
      isFlag: true,
      origin: null,
      base64: "",
      personId: "",
      isFlag2: true,
      screenWidth: 375,
      screenHeight: 640,
      faceImage: '', //人脸图片
    }
  },

  onShow: function () {
    this.setData({
      isVerify: false,
      tipsText: "",
      isFlag: true,
    })

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


    // 3、获取 Camera 实时帧数据
    const listener = this.data.cameraEngine.onCameraFrame((frame) => {
      console.log(888888888, frame.data, frame.width, frame.height)
      if (this.data.isVerify) return

      //动态设置canvas的宽高,不设置会导致部分机型人脸不完整导致不能识别-----很重要!很重要!很重要!
      if (this.data.isFlag2) {
        this.setData({
          isFlag2: false,
          screenWidth: frame.width,
          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) => {
          console.log(1111, faceData)
          let face = faceData.faceInfo[0]
          if (face.x == -1 || face.y == -1) {
            this.setData({
              tipsText: '检测不到人'
            })
          }
          if (faceData.faceInfo.length > 1) {
            this.setData({
              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.setData({
                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.setData({
                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.setData({
                  tipsText: '校验中...',
                  isVerify: true
                })
                // 太快获取的人脸可能比较抽象,给用户一个准备时间
                setTimeout(async () => {
                  let img = await this.changeDataToBase64(
                    frame);
                  this.setData({
                    base64: img
                  })
                  this.searchUserFace();
                }, 300)
              } else {
                this.setData({
                  tipsText: '请将人脸对准中心位置'
                })
              }
            }
          }
        },
        fail: (err) => {
          console.log(2222, err)
          if (this.isVerify) return
          if (err.x == -1 || err.y == -1) {
            this.setData({
              tipsText: '检测不到人'
            })
          } else {
            this.setData({
              tipsText: err.errMsg || '网络错误,请退出页面重试'
            })
          }
        },
      })
    })
    // 5、开始监听帧数据
    listener.start()
    this.setData({
      listener: listener
    })
    // #endif
  },
  reverse() {
    let a = this.data.devicePosition
    this.setData({
      devicePosition: !a
    })
  },
  clickScanCode() {
    // 只允许通过相机扫码
    // #ifdef MP-WEIXIN
    wx.scanCode({
      onlyFromCamera: true,
      success: (res) => {
        var data = JSON.parse(res.result.replace(/\ufeff/g, ""));
      }
    });
    // #endif
  },
  changeDataToBase64(frame) {
    console.log(4444, frame)
    return new Promise((resolve, reject) => {
      var data = new Uint8Array(frame.data);
      var clamped = new Uint8ClampedArray(data);
      let that = this;
      var width = this.data.screenWidth;
      var height = frame.height * this.data.screenWidth / frame.width;

      wx.canvasPutImageData({
        canvasId: 'myCanvas',
        x: 0,
        y: 0,
        width: frame.width,
        height: frame.height,
        data: clamped,
        success(res) { // 转换临时文件
          console.log(5555, res)
          wx.canvasToTempFilePath({
            x: 0,
            y: 0,
            width: width,
            height: height,
            canvasId: 'myCanvas',
            fileType: 'jpg',
            destWidth: width,
            destHeight: height, // 精度修改  
            quality: 0.5,
            success(res) {
              console.log(666, res)
              // 临时文件转base64
              wx.getFileSystemManager().readFile({
                filePath: res.tempFilePath, //选择图片返回的相对路径 
                encoding: 'base64', //编码格式  
                success: res => {
                  console.log(7777, res)
                  // 保存base64
                  resolve(res.data);
                }
              })
            },
            fail(res) {
              console.log(8888, res)
              reject(false);
            }
          });
        },
        fail(error) {
          console.log(error);
        }
      })
    })
  },

  searchUserFace() {
    // 1.人脸识别错误 把isVerify设置为true继续识别
    // 2.人脸识别成功,做对应的逻辑
    console.log(333, this.data.base64)
    this.setData({
      faceImage: 'data:image/jpeg;base64,' + this.data.base64,
      tipsText: '校验成功'
    })
    wx.stopFaceDetect(); //关闭人脸识别
    this.data.listener.stop(); //关闭camera摄像头监听
    return
    var params = {
      faceImage: this.data.base64,
    }
    searchFaces(params).then(res => {
      console.log(444, res)
      if (res.code == 200) {
        wx.stopFaceDetect(); //关闭人脸识别
        this.data.listener.stop(); //关闭camera摄像头监听
        this.clickPushDetail(res.data.personCode);
        this.setData({
          tipsText: '校验成功'
        })
      }
    }).catch(error => {
      setTimeout(() => {
        this.setData({
          isVerify: 'false'
        })
      }, 500)
      this.setData({
        tipsText: '暂未查找到相关人员'
      })
    })
  },
  clickPushDetail() {
    // 跳转到其他页面
  },

  lineAnimation() {
    if (this.timer) return
    this.setData({
      timer: setInterval(() => {
        this.setData({
          translateY: this.data.translateY + 8
        })
        if (this.data.translateY >= 460) {
          this.setData({
            translateY: 10
          })
        }
      }, 40)
    })

  },


  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

css

javascript 复制代码
/* pages/face/index.wxss */
page {
  background-color: #000000;
}

.camera-change-image {
  width: 52rpx;
  margin-left: 40rpx;
}

.scan-image {
  width: 48rpx;
}

.update-box {
  color: #ffffff;
}

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

}

.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;
}

.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;
}
相关推荐
不如摸鱼去7 小时前
Wot UI 2.1.0 发布:ConfigProvider 全局配置能力升级
ui·小程序·uni-app
这是个栗子10 小时前
微信小程序开发(九)- uni-app微信小程序商城
微信小程序·小程序·uni-app·vue·vuex
TuCoder11 小时前
景区导览小程序功能选型指南:刚需配置、增值功能与技术避坑要点
小程序
小羊Yveesss14 小时前
2026年知识付费小程序多少钱一个?
小程序
一只皮卡皮卡丘14 小时前
微信小程序tab页苹果显示安卓不显示的问题
微信小程序·小程序
六月的可乐14 小时前
【干货】小程序虚拟瀑布流探索小结
前端·react.js·小程序
前端 贾公子1 天前
小程序蓝牙打印探索与实践(上)
小程序
拙慕JULY1 天前
小程序返回 base64 文件报错
开发语言·javascript·小程序
dh131222505251 天前
按月季度销售业绩核算小程序
小程序·销售小程序·绩效小程序·业绩统计小程序·业绩核算小程序
拙慕JULY1 天前
微信小程序自定义标题背景色
微信小程序·小程序