最近花了些时间做了一个微信小程序------明星脸比对。用户上传一张照片,AI 就能找出和你最像的明星。
这个项目有点意思,因为它采用了一个不太常见的架构:前端直调腾讯云 IAI,云函数只存密钥,API 签名在前端完成。没有后台中转,零额外延迟。
今天就来聊聊这个项目的开发过程和一些技术取舍。
为什么做这个项目
想法其实很简单:大家都好奇自己长得像哪个明星。市面上类似的小程序不少,但大多需要把图片传到自己的服务器,经过后台处理后再调用 AI 服务。这样不仅慢,还增加了服务器成本。
我就在想,能不能让前端直接调用腾讯云的人脸识别服务?这样既快又省钱。
技术栈选择
前端用了 UniApp + Vue.js,目标是微信小程序。选择 UniApp 是因为一套代码可以跑多端,虽然这次只做小程序,但以后扩展方便。
人脸识别用的是腾讯云 IAI(人脸搜索 3.0)。这个服务支持在指定人员库中搜索相似人脸,返回 Top K 结果和相似度分数,正好符合需求。
后台用 Flask (Python) ,但注意,这个后台不是小程序运行必需的。它只用于批量管理人员库数据------添加明星、删除明星、初始化人员库等。小程序本身不经过这个后台。
核心架构:前端直调
这是整个项目最关键的设计决策。
传统做法是:用户上传图片 → 传到自己的服务器 → 服务器调用腾讯云 API → 返回结果。多了一跳,延迟增加,服务器还要承担转发成本。
我的做法是:用户上传图片 → 前端完成 TC3-HMAC-SHA256 签名 → 直接调用腾讯云 IAI SearchFaces 接口 → 返回结果。
云函数在这里只做一件事:安全地存储腾讯云密钥。前端通过云函数获取临时密钥,然后在前端完成 API 签名。这样既保证了密钥安全,又实现了零中转延迟。
图片处理流程
前端处理图片的流程需要仔细设计:
-
用户选择图片 :支持拍照和相册选择,优先使用
uni.chooseMedia,兼容降级到uni.chooseImage。 -
图片压缩 :这是关键一步。人脸图片不需要太高分辨率,压缩到 800px 以内可以大幅减少传输时间。先用
uni.compressImage做质量压缩,如果图片过大再用 canvas 做尺寸压缩。 -
上传到云存储:压缩后的图片上传到 uniCloud 云存储,获取永久 URL。这个 URL 用于结果页展示和分享功能。
-
转 base64:读取压缩后的图片文件,转换为 base64 编码,用于调用人脸搜索接口。
-
调用云函数:通过 uniCloud 云函数进行人脸检测和搜索。云函数内部完成签名和 API 调用。
人员库管理
腾讯云 IAI 的人脸搜索需要在指定的人员库中进行。所以第一步是建立一个明星人员库。
后台提供了完整的 CRUD 接口:
- 创建人员库
- 批量添加明星(从 JSON 文件导入)
- 搜索人脸
- 删除明星/人员库
初始化脚本 add_stars.py 会读取 data/new_cloud/ 目录下的所有 JSON 文件,批量导入到腾讯云人员库。每个明星数据包含 person_id、name、gender、url(照片 URL)等信息。
还有一个爬虫脚本 scrape_category.py,可以从网站抓取明星数据,自动生成 JSON 文件。
积分系统设计
小程序做了一个简单的积分系统:
- 每次比对消耗 5 积分
- 分享给好友可获得 5 积分
- 观看视频广告可获得 5 积分
这个设计有两个目的:一是控制 API 调用频率(腾讯云按次计费),二是通过分享实现自然增长。
积分查询和扣除通过后端 API 完成,前端只负责展示和触发。
结果展示
结果页的设计花了些心思:
- 对比展示:左边是用户上传的照片,右边是最匹配的明星,中间用 VS 图标连接,视觉冲击力强。
- 相似度进度条:把腾讯云返回的分数转换成百分比,用渐变色进度条展示,直观易懂。
- 其他相似明星:除了最匹配的一个,还展示 Top 2-5 的其他候选,增加趣味性。
- 分享优化:分享时带上用户照片作为封面,标题显示"我和 XX 相似度 XX%",吸引点击。





踩过的坑
开发过程中遇到几个值得注意的问题:
1. 图片压缩比例问题
一开始用 canvas 压缩图片时,没有保持原始宽高比,导致人脸变形,识别率大幅下降。后来改为先获取图片信息,计算缩放比例,再用 canvas 等比例绘制。
2. 云函数调用失败
前端直接调用腾讯云 API 时,签名算法容易出错。TC3-HMAC-SHA256 签名需要严格按照腾讯云文档的步骤来,包括 CanonicalRequest、StringToSign 等。建议先用官方 SDK 测试,确认签名逻辑正确后再移植到前端。
3. 人员库初始化
批量导入明星数据时,API 有频率限制。一开始没有加延迟,导致部分请求被限流。后来在每次请求后加了 0.3-0.5 秒的间隔,问题解决。
项目结构
mingxing_face/
├── admin/ # 后台管理(仅用于初始化/管理人员库)
│ ├── app.py # Flask 管理服务
│ ├── config.py # 腾讯云 API 配置
│ ├── tencent_iai.py # 腾讯云 IAI SDK 封装
│ ├── add_stars.py # 一键初始化 IAI 人员库
│ ├── scrape_category.py # 明星数据爬取脚本
│ └── data/ # 明星数据与图片
│
├── star_face_uniapp/ # UniApp 前端(微信小程序)
│ ├── pages/index/index.vue # 首页:拍照/选图 → 人脸搜索
│ └── pages/result/result.vue # 结果页:展示 Top5 相似明星
│ └── uniCloud/ # 云函数(仅存储密钥)
总结
这个项目的核心价值在于架构简化。通过前端直调云服务,省去了中间服务器层,降低了延迟和成本。
当然,这种架构也有局限:
- 前端签名逻辑暴露了部分实现细节(虽然密钥是安全的)
- 不适合需要复杂业务逻辑的场景
- 云函数的冷启动时间仍然会影响首次调用速度
但对于这种"上传-处理-返回"的简单场景,前端直调是一个值得考虑的方案。
项目代码已经开源,如果你也感兴趣,可以看看完整实现。欢迎提 issue 或 PR。
https://github.com/liandyao/ai_star_face.git
技术栈:UniApp + Vue.js | 腾讯云 IAI | uniCloud | Flask | Python
适用场景:人脸识别、图片比对、AI 趣味应用