日常记录碰到的问题:
我目前是人脸识别需要获取照片,按照当前需求所写
首先在微信小程序中拍照会使用到camera组件,该组件需要用户授权,拒绝授权的情况以后可能会补充,目前展示仅仅为允许授权的情况。
组件中设置的值根据需求查看官网进行修改,官网地址:微信小程序camera组件
page.wxml:
这里的windowHeight是我获取的手机高度,因为原生组件的层级太高,我将画布放在的页面外面并在page.json中给页面"disableScroll": true设置了不可拖动的参数
<camera wx:if="{
{!src}}" class="camera" device-position="front" frame-size="small" flash="off" binderror="error" style="">
</camera>
<canvas class="canvas" style="height:{
{
windowHeight}}px;margin-top:{
{
windowHeight}}px;" canvas-id="firstCanvas"></canvas>
page.wxss:
.camera {
width: 400rpx;
height: 400rpx;
border-radius: 50%;
z-index: 1;
}
.canvas {
width: 100%;
box-sizing: border-box;
z-index: 0;
}
最重要的是page.js文件,这里用到wx.createCameraContext()创建系统相机上下文对象,onCameraFrame获取实时帧数据,wx.canvasPutImageData将像素数据绘制到画布,wx.canvasToTempFilePath保存图片等api方法
这里解释一下为什么会用到画布:
首先采用takePhoto方法进行拍照,因为ios系统设置中有防止偷拍的设定,所以即使在静音的情况下,ios拍照也会发出咔嚓的声音,而官方文档中并没有能控制这个情况的参数,所以要采用onCameraFrame获取相机实时帧,得到的数据是未经过处理的类似于二进制的数据(个人理解),在使用画布,先用wx.canvasPutImageData将得到的图像数据画出来,在使用wx.canvasToTempFilePath方法将画布上的照片保存下来转为base64格式传给后台即可
page.js:
const app = getApp()
let listener = ''
Page({
/**
* 页面的初始数据
*/
data: {
src: null,
status: {
record: false,
camera: 'front'
},
detectLiveFace: null,
Bullet_frame: false,
serintervalTime: null,
/
device: true,
speedMaxCount: 30,//用来限制实时帧获取时间,减少后台请求与UI压力
/
windowHeight:0,//页面高度
},
onShow: function () {
let that = this
const ctx = wx.createCameraContext()
that.startTacking()//调用获取相机实时帧方法
},
//调用获取相机实时帧方法
startTacking() {
var _that = this;
var count = 0;
const context = wx.createCameraContext();
if (!context.onCameraFrame) {
var message = '基础库 2.7.0 开始支持".';
wx.showToast({
title: message,
icon: 'none'
});
return;
}
listener = context.onCameraFrame(function (res) {
// 每秒60帧,这里控制每0.5获取一次图片
// console.log('实时像素帧', res)
if (count < _that.data.speedMaxCount) {
count++;
// console.log('count count count', count)
return;
}
count = 0;
console.log('当等于30时')
// onCameraFrame 获取的是未经过编码的原始 RGBA 格式的图像数据,接下来转为图片
_that.jschangeDataToBase64(res)
});
// start
listener.start();
},
// 将实时帧在canvas上画出来,并保存的到图片路径
jschangeDataToBase64(frame) {
var data = new Uint8Array(frame.data);
var clamped = new Uint8ClampedArray(data);
let that = this
// console.log('clamped clamped', clamped)
var contex = wx.createCanvasContext('firstCanvas')
wx.canvasPutImageData({
canvasId: 'firstCanvas',
x: 0,
y: 0,
width: frame.width,
height: frame.height,
data: clamped,
success(res) {
// 转换临时文件
// console.log('转换临时文件', res)
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: frame.width,
height: frame.height,
canvasId: 'firstCanvas',
fileType: 'png',
destWidth: frame.width,
destHeight: frame.height,
// 精度修改
quality: 0.8,
success(res) {
// 临时文件转base64
let oddurl = res.tempFilePath
wx.getFileSystemManager().readFile({
filePath: res.tempFilePath,
//选择图片返回的相对路径
encoding: 'base64',
//编码格式
success: res => {
// 保存base64
let base64 = res.data;
console.log('转化完成',res)
// 拿到数据后的其他操作 调用请求接口方法,将得到的数据发送到后台
that.detectLiveFace(base64, oddurl)
}
})
},
fail(res) {
console.log(res)
wx.showToast({
title: '图片生成失败,重新检测',
icon: 'none',
duration: 1000
}) // 测试的时候发现安卓机型,转为临时文件失败,这里从新获取帧数据,再转码就能成功
}
}, that)
},
fail(res) {
console.log('调用失败', res)
}
})
},
// 结束相机实时帧
stopTacking() {
if (listener) {
listener.stop();
}
},
// 开始相机实时帧
startcamera:function(){
if(listener){
listener.start()
}
},
detectLiveFace:function(url, oddurl){
let that = this
that.stopTacking()
console.log('得到的base64图像路径',url,'之前的路径',oddurl)
//请求接口
},
})