Meta智能眼镜应用内置完整设备端人脸识别系统:检测、嵌入、向量索引与通知
- #Meta
- #智能眼镜
- #人脸识别
- #设备端AI
- #隐私
Stella是Meta智能眼镜的配套应用。通过检查Android构建版本273.0.0.21(包名com.facebook.stella),我发现其包含了完整的设备端人脸识别计算和存储栈:三个人脸模型、一个本地数据库schema、一个与模型维度匹配的余弦相似度向量索引、一个将生物特征记录暂存到磁盘的写入路径、一个功能完善的通知界面,以及一个面向用户的"连接"组件。
我需要精确说明这代表什么和不代表什么,因为两者之间的差距很重要。
我能演示的: 这些机制存在且已连接。几个面部提取和面部指纹模型存在,我能够端到端地在测试图像上运行识别流水线:检测到一张脸,生成一个2048维的生物特征嵌入向量,搜索本地索引,并在匹配成功时触发一条Android通知,告知用户"已识别出人物"。
为了运行流水线,我直接使用测试照片调用了其现有的处理程序。
我不能演示的: 其中任何部分对普通用户是激活的。在默认的、未注册的账户上,面向用户的UI不会出现,识别通知深层链接到的目标屏幕在构建中缺失。我也没有观察到Meta向我的测试账户上的相关数据库推送身份数据。
所以这并非"Meta正在秘密识别你看到的人"。而是:用于完成这一任务的完整装置已经位于设备上,组装完毕且功能正常,但由Meta控制开关。
以下所有发现均可针对com.facebook.stella v273.0.0.21复现。
设备上随附了三个面部识别模型(约100 MB)
三个ExecuTorch(.pte)模型通过Meta的资源交付系统NMLML从Meta下载到达设备:
| 资源名称(Meta命名) | 文件名 | 文件大小 | 功能 |
|---|---|---|---|
| android_facerec_scrfd | SCRFD.pte | 3.4 MB | 检测图像中的人脸 |
| android_facerec_kps_aligner | KPSAligner.pte | 117 KB | 裁剪并对齐每个检测到的人脸 |
| android_facerec_sface | SFace.pte | 96 MB | 将人脸转换为2048个数字的嵌入向量(生物特征指纹) |
这些映射到开源架构,与其他应用和学术项目已使用的模型系列相同:
- SCRFD:用于高效人脸检测的样本和计算再分配(InsightFace, ICLR 2022)。参考实现:github.com/deepinsight/insightface。
- SFace:用于人脸识别的Sigmoid约束超球面损失(Zhong et al., 2021)。参考:github.com/zhongyy/SFace。
- KPSAligner:基于关键点的对齐,自2015年以来的标准做法(MTCNN, dlib, InsightFace)。
Meta的SFace变体似乎比公开参考版本规模更大(96 MB vs. ~40 MB;2048维输出 vs. 参考版的128–512维)。
值得直说:搭载检测和嵌入模型本身并不能证明识别功能。许多应用为了取景或自动对焦而运行设备端人脸检测。
与设备端指纹生成器维度完全匹配的余弦相似度人脸索引
实际运行并读取到此数据库的识别流水线位于:/data/user/0/com.facebook.stella/files/rldrive/person_profiles/objects.db。这位于Meta的跨设备同步框架RLDrive下,位于一个旨在被远程填充的person_profiles命名空间中。我没有直接观察到Meta向我的测试账户推送person_profiles的数据。我想澄清我描述的是通道的存在,而非观察到的传输。
schema如下:
CREATE TABLE person (
nodeid INTEGER PRIMARY KEY,
name TEXT,
uri TEXT,
blob BLOB,
deleted INTEGER,
version BLOB
);
CREATE TABLE face (
nodeid INTEGER PRIMARY KEY,
mediaPath TEXT, -- 用于深层链接的face_id
personUri TEXT, -- 对person.uri的软引用
blob BLOB,
deleted INTEGER,
uri TEXT,
version BLOB
);
CREATE VIRTUAL TABLE face_mediaPath_vec USING vec0(mediaPath float[2048] distance_metric=cosine);
-- 每个人脸的2048个浮点生物特征指纹,余弦距离搜索
-- 使用sqlite-vec扩展
每张人脸行通过personUri指向一个人。每个face.mediaPath是face_mediaPath_vec的主键,后者存储2048维嵌入向量。识别过程是余弦相似度查询,然后与person.name连接以获取通知文本。
几点吻合:
vec0是开源的sqlite-vec扩展,将SQLite变成向量相似性引擎。float[2048]维度正是随应用提供的SFace嵌入器的输出形状。- 余弦度量是比较人脸嵌入的标准选择。
- 模式允许每个
personUri有多个face行(无UNIQUE约束),但从非注册设备无法看出生产部署使用的是1对1还是1对多。
端到端测试确认两条分支并隔离写入位置
我对数据库进行了SHA-256快照和行计数,然后运行了完整的识别流水线两次:一次针对空索引(无匹配),一次针对预加载了单个嵌入的索引(匹配):
- 无匹配(空
face_mediaPath_vec) :一对(uuid.jpg, uuid.emb)被写入NameTagsPending/。无通知。 - 匹配:一条Android通知通过生产环境的
nametags_recognition通道触发——标题"已识别出人物",内容"已识别出Michel Foucault"。NameTagsPending/中未添加任何内容。
未识别的人脸暂存到磁盘:裁剪图+指纹位于NameTagsPending/
当设备看到本地索引不匹配的人脸时,Stella将其写入:/data/user/0/com.facebook.stella/files/NameTagsPending/。每个未识别的人脸产生一对以新UUID命名的文件:
- 一个
.jpg——裁剪并对齐后的人脸,SCRFD + KPSAligner的输出; - 一个
.emb——2048维SFace指纹。
该目录权限为0700,重启后持久存在。写入仅在无匹配分支发生;匹配的人脸触发通知且不留磁盘痕迹。
我直接验证了嵌入向量的结构:
- 文件:
NameTagsPending/1566ab46-[...].emb - 大小:8192字节(2048 × float32,大端)
- L2范数:0.999999 ← 规范L2归一化人脸嵌入
- 最小值/最大值:−0.092110 / +0.098950
- 平均值:+0.000292
(uuid.jpg, uuid.emb) 共同构成一个完整的、可索引的人脸生物特征记录——与person_profiles/objects.db中余弦索引构建所匹配的形状和编码完全一致。
NameTagsPending字面意思是"等待名称的人脸"——生物特征编码完成,等待标签。我将指出这一结构事实,让它不言自明:一张人脸图像及其指纹,以明文形式并列存储,权限0700,重启后持久存在,这正是如果你想在之后获得标签时回溯性识别面孔所需要汇编的数据集。
(原始输入照片是1970年Jerry Bauer拍摄的Michel Foucault肖像,318×418像素JPEG,28 KB,公有领域,来自维基共享资源。Stella流水线裁剪出的人脸写入NameTagsPending/:SCRFD检测器+KPSAligner对齐后的输出,83×118像素RGB JPEG,4396字节。)
通知界面功能完善
Stella定义了一个专用的Android通知通道:
NotificationChannel{
id = "nametags_recognition"
name = "NameTags recognition"
description = "Notifications for recognized NameTags connections"
importance = IMPORTANCE_HIGH (heads-up + sound + badge)
sound = system notification sound
}
通知模板在识别处理程序中硬编码。标题始终为"已识别出人物";内容始终为"已识别出" + 名称,其中名称来自person_profiles/objects.db中的person表:
NotificationCompat.Builder(ctx, "nametags_recognition")
.setContentTitle("Person recognized")
.setContentText("Recognized " + matched_name)
.setAutoCancel(true)
.setContentIntent(
PendingIntent.getActivity(
ctx,
matched_name.hashCode(),
Intent.ACTION_VIEW with Uri "fb-viewapp://name_tags?face_id=" + face_id,
FLAG_IMMUTABLE | FLAG_UPDATE_CURRENT))
.build()
NotificationManagerCompat.notify(matched_name.hashCode(), notification)
通知可点击:其contentIntent是一个形如fb-viewapp://name_tags?face_id=<face_id>的深层链接,这是一个Meta创作的URL方案,旨在打开Stella内的人物资料屏幕。
一个诚实的警告:在v273中,我找不到那个目标屏幕。点击通知会将Stella路由到其默认标签,因为目标Compose目标在导航图中缺失。通知会触发,但它指向的屏幕并未构建在此版本中。
面向用户的"连接"入口存在于APK中
Stella v273包含一个小组件,在标题为"Connections"的节标题下渲染一张卡片,文字为"See your connections" / "Remember the people you met and make new connections."这两个字符串都是APK中硬编码的,非服务端推送。
在默认的、未注册账户上,该卡片完全不在Glasses标签页显示。在测试中它变得可见。在正常使用中,用户不会看到它。
总结
完整的设备端人脸识别技术栈:检测、对齐、嵌入、向量索引、存储、写入路径和通知界面,在Stella v273中全部存在且已组装。
它是功能完整的。端到端运行可识别已知人脸并在通知中命名,并将未知人脸(裁剪图+指纹)暂存到磁盘。
索引维度、嵌入形状和存储 schema 相互一致,这是一个连贯的系统,而非散落的死代码。
用户实际会接触的部分:"Connections"卡片和通知打开的资料页面,要么在构建中缺失,要么埋得更深。
流水线使用的数据库位于Meta服务端填充的同步命名空间中,与它已经填充的其他命名空间并列,但我没有观察到向我的账户的面部命名空间的推送。
我未声称: Meta目前正在为用户识别陌生人、注册数据正在流动,或上述任何功能已在生产中启用。
难以否认的是: 构建、交付并连接如此庞大的装置,直至2048维人脸指纹和硬编码的"已识别出人物"通知,是一项工程投资。这种能力不会偶然出现。是否以及何时投入生产,需要Meta来回答。
本研究与《连线》杂志的报道同步发布。
评论