十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

微信小程序人脸识别demo开发实战:从API选型到云函数部署

微信小程序人脸识别demo开发实战:从API选型到云函数部署 简介一份微信小程序人脸识别入门演示程序面向小程序初学者和希望快速体验人脸检测能力的开发者。资源围绕人脸识别主题提供完整的前端调用逻辑、页面交互与源码实现并配有运行截图帮助用户对照界面效果理解人脸识别接口在小程序端的接入方式。压缩包内共十三个文件四个脚本负责逻辑处理、接口调用与工具封装两个页面结构文件与三个样式文件分别对应界面布局和视觉表现三个配置文件用于项目及页面设置另有一个说明文档辅助阅读整体仅十KB紧凑易读适合逐行分析。目前已有两千一百八十八人下载学习热度较好可作为课程设计参考或人脸识别小程序起步模板。通过研读源码可以掌握全局初始化、页面目录组织方式以及工具模块对通用能力的封装思路便于迁移复用快速搭建自己的小程序功能。1. 微信小程序 demo 人脸识别为什么值得自己写一遍打开一个带“源代码截图”的人脸识别 demo第一件事不是看代码而是先确认它跑在哪一层。微信小程序几乎不可能在本地跑完一套完整的深度学习人脸识别模型常见做法是前端收集照片后端或云函数调用开放 API 完成检测再把识别框和分数画回页面。真正有信息量的不是那几行wx.request而是 API 怎么拿、请求怎么拼、检测框怎么映射到图片坐标、截屏怎么对得上。写一次这个 demo相当于把小程序上传链路、云函数鉴权、图片坐标换算和开放平台错误码全部过一遍对新手和转岗后端的人都有实际价值。2. 人脸识别小程序的技术选型与 API 取流2.1 纯前端为什么坐不了识别云 API 是默认解小程序包体积上限约 2MB主包校验后超过 1.5MB 就会被警告。一个人脸检测模型压缩后通常是 5MB 到 20MB更不要提运行时的 CPU 占用和内存水位。即便用wx.createVKSession做部分端上推理也只能覆盖人脸检测、关键点这类轻能力且对基础库版本和机型有限制。把识别放到云端前端只负责取图和渲染是大多数开源 demo 的默认结构。2.2 百度、腾讯云、旷视的免费额度怎么挑做人脸识别 demo 最怕选错平台刚开始就用付费高 QPS 接口意义不大。只看人脸检测和人脸搜索这两个能力平台人脸检测免费额度人脸搜索适合场景百度人脸识别每月免费调用量可观日常 demo 够用有需建人脸库入门最快文档找得到示例腾讯云人脸识别按量计费新用户有免费资源包有API 语义清晰如果你在腾讯云开发不用出腾讯生态旷视 Face免费版 QPS 有限制有对质量分、关键点要求高时考虑demo 阶段建议选百度原因是它的face_detect接口返回里直接带了face_probability、location、age、gender等字段方便在小程序界面里直接展示省去自己解释模型输出。需要说明的是免费额度是按账号维度计算的长时间调试时把一张图反复提交照样会耗额度开发时要在本地做图片压缩。2.3 从控制台拿到密钥用 curl 验证接口先去对应开放平台的人脸识别控制台创建应用拿到API Key和Secret Key。这两个值不能直接放进小程序前端它们要留在云端或本地服务里。用curl换access_token的命令是curl -s https://aip.baidubce.com/oauth/2.0/token?grant_typeclient_credentialsclient_idYOUR_API_KEYclient_secretYOUR_SECRET_KEY | jq -r .access_token这段命令把access_token从返回 JSON 中提取出来。jq是命令行 JSON 解析器没装的系统可以换成python -c import sys,json;print(json.load(sys.stdin)[access_token])。token有效期为 30 天demo 阶段每次调试手动跑一次即可如果做自动化需要写成缓存刷新前开始计时。拿到 token 后测试人脸检测接口curl -s https://aip.baidubce.com/rest/2.0/face/v3/detect?access_tokenYOUR_TOKEN \ -H Content-Type: application/json \ -d { image: BASE64图片内容, image_type: BASE64, face_field: age,gender,beauty,quality, max_face_num: 5 }接口要求图片转成 base64。网络图 URL 也能传但要注意域名是否是公网可访问本地调试把图片转为 base64 传给image再把image_type设成BASE64。返回结果里result.face_list[0].location是后人脸框的位置rotated_image_height和rotated_image_width表示原图尺寸后面在小程序里画框全靠它。3. 构建小程序人脸识别 demo 的源码骨架与云函数中转3.1 最小文件结构一个能上传图片、走云函数、展示检测结果的微信小程序目录大致长这样miniprogram/ pages/ index/ index.wxml index.wxss index.js index.json app.js app.json project.config.json cloudfunctions/ faceDetect/ index.js package.jsonapp.json里要添加页面路径并声明云开发配置。不使用云开发的话可以用一个 HTTPS 服务作为中转但云开发的鉴权体系和本地调试体验更简单二维码上传小程序图片时也不用手写服务器。project.config.json中的cloudfunctionRoot路径要指向cloudfunctions/开发者工具才能识别云函数目录。3.2 小程序端页面代码把图片交给云函数index.wxml只放两个核心控件上传按钮和结果画布。用button触发选择图片用cover-view或普通view在图片上叠加显示人脸框。对新手来说更简单的做法是先不画框用text把位置和年龄显示在图片下方跑通后再升级成可视化框。view classcontainer image src{{imagePath}} modeaspectFit bindtapchooseImage/ button bindtapdetectFace检测人脸/button view wx:for{{faceList}} wx:keyindex 年龄: {{item.age}}性别: {{item.gender}}概率: {{item.probability}} /view /viewconst app getApp() Page({ data: { imagePath: , faceList: [] }, chooseImage() { wx.chooseMedia({ count: 1, mediaType: [image], sizeType: [compressed], success: res { this.setData({ imagePath: res.tempFiles[0].tempFilePath }) } }) }, async detectFace() { const res await wx.cloud.callFunction({ name: faceDetect, data: { imagePath: this.data.imagePath } }) this.setData({ faceList: res.result.faceList }) } })wx.chooseMedia代替了老接口wx.chooseImage低版本基础库要注意兼容。sizeType: [compressed]能在源头减少上传体积云函数做 base64 时也更省内存。这里的核心点是数据交互小程序直接传imagePath给云函数云函数内部负责读取图片内容因此小程序端不需要引入鉴权信息。3.3 云函数代码封装鉴权和数据上报云函数用 Node.js 写下面是一个可直接运行的faceDetect/index.jsconst cloud require(wx-server-sdk) const axios require(axios) const fs require(fs) const path require(path) cloud.init() // 这些值应该写到云开发环境变量中不直接硬编码 const API_KEY YOUR_API_KEY const SECRET_KEY YOUR_SECRET_KEY async function getAccessToken() { const url https://aip.baidubce.com/oauth/2.0/token const res await axios.get(url, { params: { grant_type: client_credentials, client_id: API_KEY, client_secret: SECRET_KEY } }) return res.data.access_token } async function getImageBase64(filePath) { const buffer fs.readFileSync(filePath) return buffer.toString(base64) } exports.main async (event) { const token await getAccessToken() const file cloud.getWXContext().ENV local ? event.imagePath : event.fileID const base64 await getImageBase64(file) const detect await axios({ method: POST, url: https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token${token}, data: { image: base64, image_type: BASE64, face_field: age,gender,beauty,quality, max_face_num: 5 } }) return { faceList: detect.data.result.face_list.map(item ({ age: item.age, gender: item.gender.type male ? 男 : 女, probability: item.face_probability, location: item.location })) } }云函数里cloud.getWXContext()可以拿到OPENID如果将来要统计不同用户的调用量这个就是天然标识。fs.readFileSync(filePath)只适用于云函数本地临时目录如果前端传的是云存储fileID要用cloud.downloadFile取回临时链接再接 buffer。上面的代码走的是最简单路线把imagePath当作云函数绝对路径看待实际开发时建议用云存储。3.4 演示截图怎么放进项目里标题带了“截图”说明读者默认希望看到效果预览。自己维护一个screenshot/目录把开发者工具的模拟器截图放进去并在根目录README.md里引用。截图能说明三件事输入图片、识别成功、UI 排版。不要截一张没有检测框的空白页面那会被当作项目没有跑通。4. 人脸检测必调参数、边缘情况与避坑4.1 三个值得优先调教的参数第一个是max_face_num。它的默认值是 1如果图片里有两个人只有一个人被返回。demo 把 5 见过多少就 5但也要注意 API 的并发上限连续高频调用容易触发平台限流。第二个是min_face_size。单位是像素默认值是 40。过小会识别出无数小噪声框过大则漏检头像较小的场景。做门禁场景和自拍场景的取值差别很大建议先在测试图集上跑一遍找到低于某个值肉眼不再能识别为人的临界点。第三个是face_field里是否要quality。quality中包含模糊程度和遮挡程度如果不加这个字段face_probability只能告诉你“像不像人脸”不能告诉你“这张图能不能用来对比”。小程序的用户随手拍照经常有光线差、低头看屏的情况加上quality后可以在前端拦截低质量图避免把无效图片传给付费接口。4.1.1 用一行代码控制人脸检测的阈值云函数端可以在axios请求前先判断质量参数const quality detect.data.result.face_list[0].quality if (quality.blur 0.2) { return { code: IMAGE_TOO_BLUR } }这样用户拿到错误提示后会重新拍摄而不是看着一个错误码不知道该怎么办。4.2 常见的网络错误与提示优化小程序和人脸识别 API 之间的链路有四个环节微信上传 → 云函数 → 开放平台 → 返回结果。哪个环节出问题表现都不一样。下表整理了 demo 阶段最常遇到的情况现象可能原因排查方法云函数调用超时图片太大或接口响应慢云函数内存调到 512MB超时调到 20s返回错误码提示 base64 过长图片未压缩前端用压缩尺寸或云函数里再压缩一次返回 QPS limit免费额度限制在云函数中加队列或降频token 过期超过 30 天用getAccessToken每次刷新或加内存缓存检测不出人脸图片模糊或人脸过小调min_face_size引导用户正对镜头云函数的日志是这个 debug 过程里最好的放大镜。在云开发控制台 → 云函数 → 日志中能看到每一次调用的耗时、内存和return结果。加日志的最简单手段是console.log(JSON.stringify(detect.data))别怕输出多demo 阶段日志多比少好。4.3 处理多余的人脸与多人场景当max_face_num大于 1 时返回列表顺序不保证是图片中的左右顺序而是置信度从高到低。如果你要做“主人物优先”的逻辑可以用location里left和width推算人脸区域面积面积最大的人通常排第一位。这个逻辑在小程序前端计算即可function pickMainFace(faceList) { return faceList.sort((a, b) { const areaA a.location.width * a.location.height const areaB b.location.width * b.location.height return areaB - areaA })[0] }注意location字段中的top、left是相对旋转后图片的坐标如果页面用image的modeaspectFit展示坐标系会被缩放需要按图片实际渲染宽度 / 原始宽度比例重新换算这一步是很多人截图后对不上框的主要原因。5. 从 demo 到可交付人脸库比对、阈值与截图留存demo的下一阶段是接入人脸搜索。做法是在云函数里调用face_search接口把用户刚刚上传的图片与人脸库中的uid比对。相比人脸检测这一步才回答“这个人是谁”。注册人脸库的时机通常是在拍照页里加一个添加人员按钮前端把用户信息存到云开发数据库表结构里含face_token后续搜索返回score超过 80 时判定为同一个人。const search await axios({ method: POST, url: https://aip.baidubce.com/rest/2.0/face/v3/search?access_token${token}, data: { image: base64, image_type: BASE64, group_id_list: visitor_2025, quality_control: NONE, liveness_control: NONE } }) const score search.data.result.user_list[0].score const passed score 80quality_control和liveness_control是防伪的两个开关。demo 可以都设为NONE如果做实际门禁场景至少要开quality_control否则一张模糊的照片也能匹配成功。score阈值对人脸库中的人数和照片质量非常敏感常见做法是先收集 100 张用户照片跑一遍画出正负样本的分数分布再用分布曲线的交叉点作为阈值。截图的留存也一样重要。每次检测通过后把imagePath、score、uid和检测时间一起写入云开发数据库之后在管理端页面里直接查记录能直观评估 demo 的真实效果select uid, score, create_time from face_log order by create_time desc limit 20;云开发控制台自带简易数据查询不需要特意接 MySQL。对于一次完整的人脸识别 demo这个日志表就是可交付的最后一个印记记录多少张照片识别成功、多少张失败、失败原因是什么。把失败样本重新丢回百度后台用图片编辑工具看一眼多数问题会集中在逆光和低头要么提示用户重拍要么在入口处增加人脸框引导。调整到这里一个带源代码和截图的 demo 才算真正从“能跑”变成“能讲”。本文还有配套的精品资源点击获取
返回列表