【人脸实时追踪,看你往哪跑】微信小程序实现
756665228 发布于2019-09-02 18:48 浏览:2150 回复:9
1
收藏
最后编辑于2020-05-27

本文基于百度AI人脸识别接口。做一个在微信小程序进行人脸实时追踪并标注人脸的一些基础信息的展示。

完整的代码地址: https://gitee.com/xshuai/easydlsmartappdemo/tree/master/pages/face

本文讲解的代码不需要任何后台技术哦

先看一下效果

需要用到的工具和其他数据

1.微信开发者工具

2.百度AI人脸识别应用的两个参数APIKEY、SECRETKEY

  • 制作一个简单的页面face.wxml

相机不支持开发工具预览哦。效果必须要在手机上查看
需要对微信小程序的camera进行一定的了解哦。
画框是需要了解canvas组件哦。
这里为了演示就不额外讲解了
    

  • 相关的CSS内容face.wxss
.preview-tips {
  margin: 50rpx 0  30rpx;  
}

.video {
  margin: 20rpx auto;
  width: 100%;
  height: 300px;
}
switch{
    zoom: 0.8;
}
page {
  background-color: #F8F8F8;
  height: 100%;
  font-size: 32rpx;
  line-height: 1.6;
}
.weui-cell_ft{
  font-size: 32rpx;
}

.page-body-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

.btn-area {
  margin-top: 40rpx;
  box-sizing: border-box;
  width: 100%;
  padding: 0 30rpx;
}
  • 页面样式截图

  • 需要百度AI提供的内容
1.获取AccessToken的接口  https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=APIKEY&client_secret=SECRETKEY
2.人脸识别的接口 https://aip.baidubce.com/rest/2.0/face/v3/detect

推荐自己的账号进行企业认证哦。这样QPS就有10个了。要不然效果出不来。会提示QPS超额
  • 为了方便。进入页面优先获取一次AccessToken

相关参数可以放在face.js或者app.js中

//app.js
App({
  onLaunch: function () {
    // 展示本地存储能力
    var logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)
  },
  globalData: {
    userInfo: null,
    apiKey:'APIKEY',
    secretKey:'SECRETKEY'
  }
})

需要在face.js中的onLoad方法中进行AccessToken获取操作。得到AccessToken赋值给全局变量中。方便后续接口使用

 onLoad() {
    var that = this
     wx.showLoading({
      title: '努力加载中',
      mask: true
    })
    //屏幕宽度
    var sysInfo = wx.getSystemInfoSync()
    console.info(sysInfo.windowHeight);
    that.setData({
      windowWidth: sysInfo.windowHeight*0.75,
    })
    that.ctx = wx.createCameraContext()
    // 每次更新access_token
    wx.request({
      url: "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=" + app.globalData.apiKey + "&client_secret=" + app.globalData.secretKey,
      method: 'POST',
      dataType: "json",
      header: {
        'content-type': 'application/json'
      },
      success: function (res) {
         console.log(res.data.access_token);
        that.setData({
          access_token: res.data.access_token
        });
      }
    })
    wx.hideLoading()
  },
  • 接下来对相机组件进行处理

当点击进行人脸追踪后。更改按钮文字 为 停止人脸追踪 ,进行自动拍照操作。代码还是在face.js中

track(e) {
    var that = this
    if (e.target.dataset.trackshow == "进行人脸追踪") {
      that.setData({
        trackshow: "停止人脸追踪",
        canvasshow: true
      })
      that.takePhoto()
      //进行300ms延迟循环拍照。这里根据自己的QPS来确定。如果是默认的2  建议给1000(即1秒一拍)
      that.interval = setInterval(this.takePhoto, 300)
    } else {
      clearInterval(that.interval)
      that.setData({
        trackshow: "进行人脸追踪",
        canvasshow: false
      })
    }
  },

拍照后拿到图片真实高宽数据、转BASE64后调用人脸识别接口。接口识别成功返回数据解析数据获取人脸位置信息。通过canvas进行画框到相机框中

  takePhoto() {
    console.log(" 开始拍照 takePhoto")
    var that = this
    var takephonewidth
    var takephoneheight
    that.ctx.takePhoto({
      quality: 'low',
      success: (res) => {
        // 获取图片真实宽高
        wx.getImageInfo({
          src: res.tempImagePath,
          success: function (res) {
            console.log(res.height);
            takephonewidth = res.width,
              takephoneheight = res.height
          }
        })
        wx.getFileSystemManager().readFile({
          filePath: res.tempImagePath, //选择图片返回的相对路径
          encoding: 'base64', //编码格式
          success: res => { //成功的回调
            wx.request({
              url: "https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=" + that.data.access_token,
              data: {
                image: res.data,
                image_type: "BASE64",
                max_face_num: 10,
                face_field:'age,beauty,emotion'
              },
              method: 'POST',
              dataType: "json",
              header: {
                'content-type': 'application/json'
              },
              success: function (res) {
                console.log(res.data.error_code);
                if (res.data.error_code === 0) {
                  var ctx = wx.createCanvasContext('canvas');
                  ctx.setStrokeStyle('#31859c')//边框颜色
                  ctx.setLineWidth(3)
                  for (let j = 0; j < res.data.result.face_num; j++) {
                    var cavansl = res.data.result.face_list[j].location.left / takephonewidth * that.data.windowWidth
                    var cavanst = res.data.result.face_list[j].location.top / takephoneheight * that.data.windowWidth
                    var cavansw = res.data.result.face_list[j].location.width / takephonewidth * that.data.windowWidth
                    var cavansh = res.data.result.face_list[j].location.height / takephoneheight * that.data.windowWidth
                    var emotionType = res.data.result.face_list[j].emotion.type;
                    var emotion = '';
                    if (emotionType =='angry'){
                      emotion = '愤怒';
                    }else if (emotionType == 'disgust') {
                      emotion = '厌恶';
                    }else if (emotionType == 'fear') {
                      emotion = '恐惧';
                    }else if (emotionType == 'happy') {
                      emotion = '高兴';
                    }else if (emotionType == 'sad') {
                      emotion = '伤心';
                    }else if (emotionType == 'surprise') {
                      emotion = '惊讶';
                    } else if (emotionType == 'neutral'){
                      emotion = '无情绪';
                    }else{
                      emotion = '未知表情';
                    }
                    var cavanstext = '年龄:' + res.data.result.face_list[j].age + ' 颜值:' + res.data.result.face_list[j].beauty + ' 表情:' + emotion
                    ctx.setFontSize(14);
                    ctx.setFillStyle("#07C160")//文本颜色
                    ctx.fillText(cavanstext, cavansl, cavanst - 2)
                    ctx.strokeRect(cavansl, cavanst, cavansw, cavansh)
                  }
                  ctx.draw();
                } else {
                  var cavanstext = "未能检测到人脸";
                  var ctx = wx.createCanvasContext('canvas')
                  ctx.setFillStyle("#07C160")
                  ctx.fillText(cavanstext, takephonewidth, takephoneheight)
                  ctx.draw();
                }
              },
            })

          }
        })
      }
    })
  }

这样整个内容就完毕了。其实本次分享内容还是比较简单的。目前人脸检测接口最多支持检测10个人脸哦

大家想体验一下呢?可以微信小程序搜索 有点小帅AI

完整的代码地址: https://gitee.com/xshuai/easydlsmartappdemo/tree/master/pages/face

感谢 https://blog.csdn.net/ffcjjhv/article/details/86522208 的代码

 

收藏
点赞
1
个赞
共9条回复 最后由756665228回复于2020-05-27 09:59
#5756665228回复于2019-12-23 14:58:28

face.js

var app = getApp();
Page({
  data: {
    src: "",
    camera:"front",
    windowWidth: 0,
    trackshow: "进行面容追踪",
    canvasshow: true,
    access_token: ''
  },

  onLoad() {
    var that = this
    setTimeout(function () {
      wx.showLoading({
        title: '上传中...',
        success: function (res) {
          console.log("showLoading success", res)
        },
        fail: function (res) {
          console.log("showLoading fail", res)
        },
      })
    },500)
    //  wx.showLoading({
    //   title: '努力加载中',
    //   mask: true
    // })
    //屏幕宽度
    var sysInfo = wx.getSystemInfoSync()
    console.info(sysInfo.windowHeight);
    that.setData({
      windowWidth: sysInfo.windowHeight*0.75,
    })
    that.ctx = wx.createCameraContext()
    // 每次更新access_token
    wx.request({
      url: "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=" + app.globalData.apiKey + "&client_secret=" + app.globalData.secretKey,
      method: 'POST',
      dataType: "json",
      header: {
        'content-type': 'application/json'
      },
      success: function (res) {
         console.log(res.data.access_token);
        that.setData({
          access_token: res.data.access_token
        });
      }
    })
    wx.hideLoading()
  },

  onReady: function () {
  },
  //切换摄像头
  switch1Change: function (e) {
    if (e.detail.value) {
      this.setData({ camera: 'front' })
    } else {
      this.setData({ camera: 'back' })
    }
  },
  track(e) {
    var that = this
    if (e.target.dataset.trackshow == "进行面容追踪") {
      that.setData({
        trackshow: "停止面容追踪",
        canvasshow: true
      })
      that.takePhoto()
      that.interval = setInterval(this.takePhoto, 300)
    } else {
      clearInterval(that.interval)
      that.setData({
        trackshow: "进行面容追踪",
        canvasshow: false
      })
    }
  },

  takePhoto() {
    console.log(" 开始拍照 takePhoto")
    var that = this
    var takephonewidth
    var takephoneheight
    that.ctx.takePhoto({
      quality: 'low',
      success: (res) => {
        // 获取图片真实宽高
        wx.getImageInfo({
          src: res.tempImagePath,
          success: function (res) {
            console.log(res.height);
            takephonewidth = res.width,
              takephoneheight = res.height
          }
        })
        wx.getFileSystemManager().readFile({
          filePath: res.tempImagePath, //选择图片返回的相对路径
          encoding: 'base64', //编码格式
          success: res => { //成功的回调
            wx.request({
              url: "https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=" + that.data.access_token,
              data: {
                image: res.data,
                image_type: "BASE64",
                max_face_num: 10,
                face_field:'age,beauty,emotion'
              },
              method: 'POST',
              dataType: "json",
              header: {
                'content-type': 'application/json'
              },
              success: function (res) {
                console.log(res.data.error_code);
                if (res.data.error_code === 0) {
                  var ctx = wx.createCanvasContext('canvas');
                  ctx.setStrokeStyle('#31859c')//边框颜色
                  ctx.setLineWidth(3)
                  for (let j = 0; j < res.data.result.face_num; j++) {
                    var cavansl = res.data.result.face_list[j].location.left / takephonewidth * that.data.windowWidth
                    var cavanst = res.data.result.face_list[j].location.top / takephoneheight * that.data.windowWidth
                    var cavansw = res.data.result.face_list[j].location.width / takephonewidth * that.data.windowWidth
                    var cavansh = res.data.result.face_list[j].location.height / takephoneheight * that.data.windowWidth
                    var emotionType = res.data.result.face_list[j].emotion.type;
                    var emotion = '';
                    if (emotionType =='angry'){
                      emotion = '愤怒';
                    }else if (emotionType == 'disgust') {
                      emotion = '厌恶';
                    }else if (emotionType == 'fear') {
                      emotion = '恐惧';
                    }else if (emotionType == 'happy') {
                      emotion = '高兴';
                    }else if (emotionType == 'sad') {
                      emotion = '伤心';
                    }else if (emotionType == 'surprise') {
                      emotion = '惊讶';
                    } else if (emotionType == 'neutral'){
                      emotion = '无情绪';
                    }else{
                      emotion = '未知表情';
                    }
                    var cavanstext = '年龄:' + res.data.result.face_list[j].age + ' 颜值:' + res.data.result.face_list[j].beauty + ' 表情:' + emotion
                    ctx.setFontSize(14);
                    ctx.setFillStyle("#07C160")//文本颜色
                    ctx.fillText(cavanstext, cavansl, cavanst - 2)
                    ctx.strokeRect(cavansl, cavanst, cavansw, cavansh)
                  }
                  ctx.draw();
                } else {
                  var cavanstext = "未能检测到人脸";
                  var ctx = wx.createCanvasContext('canvas')
                  ctx.setFillStyle("#07C160")
                  ctx.fillText(cavanstext, takephonewidth, takephoneheight)
                  ctx.draw();
                }
              },
            })

          }
        })
      }
    })
  },
  error(e) {
    console.log(e.detail)
  },
  onShareAppMessage: function () {
    return {
      title: '一起颜值呀',
      path: '/pages/face/face',
      imageUrl:'/images/xs2.jpg'
    }
  },

})
0
#10756665228回复于2020-05-27 09:59:30
#9 YuandiNong回复
楼主大神你好,向你学习了!我尝试了你的代码,摄像头没有问题,前后摄像头切换也没有问题,申请了百度AI的接口,但是面容追踪还是没能成功。Q:175047456,想请教一下,可以加q吗?谢谢了~
展开

这个是一个一个抓拍的。小程序也是一直迭代变化的。升级后如果有一定的问题。我也解决不了。得看官方的升级说明。

1
#9YuandiNong回复于2020-05-26 22:38:07

楼主大神你好,向你学习了!我尝试了你的代码,摄像头没有问题,前后摄像头切换也没有问题,申请了百度AI的接口,但是面容追踪还是没能成功。Q:175047456,想请教一下,可以加q吗?谢谢了~

0
#8756665228回复于2020-02-21 09:36:36
#6 你笑的弧度f回复
拍照时有声音怎么办?

这个是的。微信小程序还有直接读取视频流的api。你可以试试看。

1
#7wangwei8638回复于2020-02-20 21:05:48
#6 你笑的弧度f回复
拍照时有声音怎么办?

那有什么影响

0
#6你笑的弧度f回复于2020-02-20 20:34:57

拍照时有声音怎么办?

0
#4wangwei8638回复于2019-09-25 21:40:43

不错,支持一下

0
#3756665228回复于2019-09-03 18:27:50
#2 晴天小秀才回复
这个属于活体检测吗,需要摇头,眨眼等一系列动作那种人脸采集?

不是哦。只是个人脸检测。

1
#2晴天小秀才回复于2019-09-03 10:19:56

这个属于活体检测吗,需要摇头,眨眼等一系列动作那种人脸采集?

0
TOP
切换版块