版本: 1.1 | 日期: 2026-04-08 | 平台: Android (minSdk 26)-理论最低是API24/Andorid 7.0
本文档基于 FacePPTest 项目的实际集成经验编写,覆盖从依赖配置到各模型的使用方式、预处理细节、精度调优和资源开销,可直接复用到其他 Android 项目。
一、架构总览
┌─────────────────────────────────────────────────────┐
│ Application Layer │
│ BeautyScoreActivity / FaceCompareActivity / ... │
├─────────────────────────────────────────────────────┤
│ LiteRTManager (Facade) │
│ init() / release() / detectFaces() / compareFaces() │
├──────────┬──────────────────────────────────────────┤
│ MediaPipe Tasks Vision │ LiteRT Interpreter │
│ ┌──────────────────────┐ │ ┌────────────────┐ │
│ │ FaceDetector │ │ │ FaceNet-512 │ │
│ │ FaceLandmarker │ │ │ (TFLite model) │ │
│ │ ObjectDetector │ │ └────────────────┘ │
│ │ ImageClassifier │ │ │
│ └──────────────────────┘ │ │
├──────────┴──────────────────────┴─────────────────────┤
│ Android Assets (模型文件) │
│ blaze_face_short_range.tflite | face_landmarker.task │
│ efficientdet_lite0.tflite | efficientnet_lite0.tflite│
│ facenet_512.tflite │
└─────────────────────────────────────────────────────┘
核心原则:完全离线,不依赖 Google Play Services、云 API 或任何第三方服务。
二、依赖配置
build.gradle.kts
dependencies {
// MediaPipe Tasks Vision — 人脸检测/特征点/物体检测/图像分类
// 内含 FaceDetector, FaceLandmarker, ObjectDetector, ImageClassifier implementation("com.google.mediapipe:tasks-vision:0.10.33")
// LiteRT 1.x Interpreter — 运行自定义 TFLite 模型(如 FaceNet)
implementation("com.google.ai.edge.litert:litert-api:1.0.1") implementation("com.google.ai.edge.litert:litert:1.0.1")
// GPU 加速(可选)
implementation("com.google.ai.edge.litert:litert-gpu:1.0.1") implementation("com.google.ai.edge.litert:litert-gpu-api:1.0.1")}关键说明
| 依赖 | 用途 | 说明 |
|---|---|---|
mediapipe:tasks-vision | MediaPipe 所有视觉任务 | 包含 FaceDetector, FaceLandmarker, ObjectDetector, ImageClassifier 等 Task API |
litert-api | TFLite Interpreter API | 提供 org.tensorflow.lite.Interpreter 类 |
litert | TFLite 运行时 | 包含原生 .so 库(libtensorflowlite_jni.so) |
litert-gpu | GPU Delegate 原生库 | 包含 libtensorflowlite_gpu_jni.so |
litert-gpu-api | GPU Delegate API | 提供 GpuDelegate、CompatibilityList 类 |
版本兼容注意
- 不要同时使用
litert:2.x和mediapipe:tasks-vision,两者的原生库可能冲突。 - 不要添加
litert-support,它与litert-support-api(MediaPipe 的传递依赖)存在 namespace 冲突。 - GPU 加速需额外添加
litert-gpu:1.0.1+litert-gpu-api:1.0.1。 - MediaPipe
tasks-vision:0.10.33不需要 Google Play Services。
三、模型清单与资源大小
所有模型存放在 app/src/main/assets/ 目录,打包进 APK。
| 模型文件 | 大小 | 来源 | 输入 | 输出 | 用途 |
|---|---|---|---|---|---|
blaze_face_short_range.tflite | 224 KB | MediaPipe | Bitmap (any size) | Bounding Box + 置信度 | 人脸检测 |
face_landmarker.task | 3.6 MB | MediaPipe | Bitmap (any size) | 478 landmarks + 52 blendshapes | 特征点 + 表情分析 |
efficientdet_lite0.tflite | 4.4 MB | MediaPipe | 320×320 | COCO 80 类 + Box | 物体检测 |
efficientnet_lite0.tflite | 18 MB | MediaPipe | 224×224 | ImageNet 1000 类 | 图像分类 |
facenet_512.tflite | 45 MB | deepface | 160×160 RGB | 512-D float vector | 人脸嵌入 |
Assets 合计: ~71 MB
缩小体积方案
| 当前模型 | 替代方案 | 新大小 | 精度影响 |
|---|---|---|---|
facenet_512.tflite (45MB) | facenet.tflite (128维) | ~11MB | 精度略低 |
efficientnet_lite0.tflite (18MB, float32) | int8 量化版 | ~5MB | 精度基本不变 |
efficientdet_lite0.tflite (4.4MB, int8) | 已是 int8 | - | - |
四、各功能模块详解
4.1 人脸检测 — MediaPipe FaceDetector
Helper 类: MediaPipeFaceHelper.kt
功能: 在图片中定位所有人脸的 Bounding Box 和置信度。
初始化:
val baseOptions = BaseOptions.builder()
.setModelAssetPath("blaze_face_short_range.tflite") .build()val options = FaceDetector.FaceDetectorOptions.builder()
.setBaseOptions(baseOptions) .setRunningMode(RunningMode.IMAGE) .setMinDetectionConfidence(0.5f) .build()val detector = FaceDetector.createFromOptions(context, options)使用:
val mpImage = BitmapImageBuilder(bitmap).build()
val result = detector.detect(mpImage)
for (det in result.detections()) {
val box = det.boundingBox() // android.graphics.Rect val score = det.categories()[0].score() // Float 0~1}输出: List<FaceRect(rect: RectF, confidence: Float)>
性能: CPU ~5-15ms (Pixel 级设备)
4.2 人脸特征点 + 表情 (Blendshapes) — MediaPipe FaceLandmarker
Helper 类: FaceLandmarkerHelper.kt
功能: 478 个 3D 面部特征点 + 52 种 Blendshape 系数(可用于情感推断)。
初始化:
val options = FaceLandmarker.FaceLandmarkerOptions.builder()
.setBaseOptions(BaseOptions.builder() .setModelAssetPath("face_landmarker.task").build()) .setRunningMode(RunningMode.IMAGE) .setNumFaces(1) .setMinFaceDetectionConfidence(0.5f) .setOutputFaceBlendshapes(true) // 关键:开启 Blendshapes .setOutputFacialTransformationMatrixes(false) .build()val landmarker = FaceLandmarker.createFromOptions(context, options)52 种 Blendshapes 关键系数:
| 系数名 | 含义 | 情感用途 |
|---|---|---|
mouthSmileLeft/Right | 嘴角上扬 | 开心 |
mouthFrownLeft/Right | 嘴角下垂 | 悲伤 |
jawOpen | 张嘴程度 | 惊讶 |
browDownLeft/Right | 眉头下压 | 生气 |
browInnerUp | 眉头上挑 | 悲伤/忧虑 |
eyeWideLeft/Right | 眼睛睁大 | 惊讶/恐惧 |
eyeSquintLeft/Right | 眯眼 | 生气/笑 |
eyeBlinkLeft/Right | 眨眼 | 活体检测 |
mouthPucker | 嘟嘴 | — |
cheekPuff | 鼓腮 | — |
情感推断逻辑(规则引擎):
开心: mouthSmileAvg > 0.3
惊讶: jawOpen > 0.5 && eyeWideAvg > 0.3
生气: browDownAvg > 0.3 && eyeSquintAvg > 0.3
悲伤: mouthFrownAvg > 0.3 && browInnerUp > 0.3
恐惧: browOuterUpAvg > 0.3 && eyeWideAvg > 0.2
中性: 以上均不满足
性能: CPU ~30-70ms
4.3 人脸嵌入 (Face Embedding) — LiteRT + FaceNet-512
Helper 类: FaceEmbeddingHelper.kt
功能: 将裁切的人脸图像转换为 512 维向量,用于人脸比对和搜索。
流水线:
原图 → MediaPipe 检测人脸框 → 裁切(+15% margin) → 缩放到 160×160 → FaceNet → 512-D L2归一化向量
预处理(极其关键):
// deepface 导出的 FaceNet-512 使用 pixel / 255.0 归一化
for (px in pixels) {
buf.putFloat((px shr 16 and 0xFF) / 255f) // R buf.putFloat((px shr 8 and 0xFF) / 255f) // G buf.putFloat((px and 0xFF) / 255f) // B}警告: 不同来源的 FaceNet 模型预处理不同!
- deepface 导出版:
pixel / 255.0→ [0, 1]- 原版 Google FaceNet: per-image standardization
(pixel - mean) / std- 错误的预处理会导致精度大幅下降!
模型加载:
val fd = context.assets.openFd("facenet_512.tflite")
val model = FileInputStream(fd.fileDescriptor).channel.map(
FileChannel.MapMode.READ_ONLY, fd.startOffset, fd.declaredLength)
val options = Interpreter.Options().apply {
setNumThreads(4) setUseXNNPACK(true) // 启用 XNNPACK 加速
}
val interpreter = Interpreter(model, options)比对逻辑:
val sim = cosineSimilarity(embedding1, embedding2) // [-1, 1]
// 置信度映射:
// cosine ≤ 0.0 → 0 分
// cosine = 0.72 → 90 分 (同一人阈值)
// cosine ≥ 0.9 → 100 分阈值建议:
| 场景 | 推荐 cosine 阈值 | 置信度 |
|---|---|---|
| 高安全(支付) | ≥ 0.8 | ≥ 95 |
| 标准匹配 | ≥ 0.72 | ≥ 90 |
| 宽松匹配(搜索) | ≥ 0.5 | ≥ 63 |
性能: CPU ~150-300ms (Pixel 级), ~80-150ms (with XNNPACK)
4.4 物体检测 — MediaPipe ObjectDetector (EfficientDet-Lite0)
Helper 类: ObjectDetectorHelper.kt
功能: 识别图片中的物体(COCO 80 类),返回标签 + 置信度 + Bounding Box。
初始化:
val options = ObjectDetector.ObjectDetectorOptions.builder()
.setBaseOptions(BaseOptions.builder() .setModelAssetPath("efficientdet_lite0.tflite").build()) .setRunningMode(RunningMode.IMAGE) .setScoreThreshold(0.3f) .setMaxResults(10) .build()val detector = ObjectDetector.createFromOptions(context, options)COCO 80 类常见标签: person, bicycle, car, motorcycle, bus, cat, dog, chair, laptop, cell phone, book, cup, bottle, clock, tie, handbag, backpack, umbrella, scissors, …
性能: CPU ~30ms (int8 量化版)
4.5 图像分类 — MediaPipe ImageClassifier (EfficientNet-Lite0)
Helper 类: ImageClassifierHelper.kt
功能: 返回图片的 ImageNet 1000 类分类标签和概率。
初始化:
val options = ImageClassifier.ImageClassifierOptions.builder()
.setBaseOptions(BaseOptions.builder() .setModelAssetPath("efficientnet_lite0.tflite").build()) .setRunningMode(RunningMode.IMAGE) .setMaxResults(10) .setScoreThreshold(0.05f) .build()val classifier = ImageClassifier.createFromOptions(context, options)典型输出示例(人脸照片):
1. suit (23.5%)
2. bow tie (8.2%)
3. Windsor tie (5.1%)
4. sunglasses (3.8%)
性能: CPU ~24ms (float32), ~10ms (int8)
4.6 图像质量评估 — 纯算法
Helper 类: ImageQualityHelper.kt
功能: 评估图像亮度和清晰度,不依赖任何模型。
亮度计算:
luminance = 0.299 * R + 0.587 * G + 0.114 * B // ITU-R BT.601 标准
brightness = mean(luminance_all_pixels)| 亮度值 | 等级 |
|---|---|
| < 50 | 过暗 |
| 50-80 | 偏暗 |
| 80-180 | 正常 |
| 180-220 | 偏亮 |
| > 220 | 过亮 |
清晰度计算 (Laplacian 方差):
Laplacian 核: [0,1,0; 1,-4,1; 0,1,0]
sharpness = variance(laplacian_output)
| 清晰度值 | 等级 |
|---|---|
| < 20 | 模糊 |
| 20-80 | 略模糊 |
| 80-300 | 清晰 |
| > 300 | 非常清晰 |
性能: < 10ms
五、Facade 模式 — LiteRTManager
object LiteRTManager {
fun init(context: Context, useGpu: Boolean = false) // 初始化 FaceDetector + FaceNet fun release() // 释放资源
fun detectFaces(bitmap): List<FaceRect> fun hasFace(bitmap): Boolean fun extractEmbedding(bitmap, faceRect): FloatArray fun extractFirstFaceEmbedding(bitmap): FloatArray? fun compareFaces(bitmap1, bitmap2): CompareResult val useGpu: Boolean // 当前是否启用 GPU}使用方式:
// Activity.onCreate — CPU 模式
LiteRTManager.init(this)
// Activity.onCreate — GPU 加速模式
LiteRTManager.init(this, useGpu = true)
// 比对
val result = LiteRTManager.compareFaces(bitmap1, bitmap2)
if (result.isSamePerson) { /* cosine >= 0.72 */ }
// Activity.onDestroy
LiteRTManager.release()六、本地向量存储 — EmbeddingDbHelper
Helper 类: EmbeddingDbHelper.kt
使用轻量 SQLite 存储人脸嵌入(无 Room、无 Google 依赖)。
val db = EmbeddingDbHelper(context)
db.insertFace("张三", embedding) // 保存
val faces = db.getAllFaces() // 查询所有
db.deleteById(id) // 删除
db.deleteAll() // 清空
// 向量序列化: FloatArray ↔ ByteArray (Little-Endian)七、复用到新项目的步骤
Step 1: 添加依赖
implementation("com.google.mediapipe:tasks-vision:0.10.33")
implementation("com.google.ai.edge.litert:litert-api:1.0.1")
implementation("com.google.ai.edge.litert:litert:1.0.1")
// 如需 GPU 加速(推荐)
implementation("com.google.ai.edge.litert:litert-gpu:1.0.1")
implementation("com.google.ai.edge.litert:litert-gpu-api:1.0.1")Step 2: 下载模型到 app/src/main/assets/
按需选择(见第三节模型清单)。
Step 3: 复制 Helper 类
从 com.example.facepptest.ml 包中按需复制:
MediaPipeFaceHelper.kt— 人脸检测FaceLandmarkerHelper.kt— 特征点 + 表情FaceEmbeddingHelper.kt— 人脸嵌入(需 LiteRT)ObjectDetectorHelper.kt— 物体检测ImageClassifierHelper.kt— 图像分类ImageQualityHelper.kt— 图像质量(纯算法,无依赖)EmbeddingDbHelper.kt— 向量存储
Step 4: 初始化
// MediaPipe 的 Helper 需要在后台线程初始化(首次加载模型较慢)
Thread {
LiteRTManager.init(applicationContext)}.start()八、GPU 加速
8.1 概述
所有 MediaPipe Tasks 和 LiteRT Interpreter 均支持 GPU 加速。GPU delegate 利用 OpenGL ES 3.1 / OpenCL 在移动设备 GPU 上执行推理,可显著降低延迟。
8.2 MediaPipe Tasks GPU 配置
MediaPipe 通过 BaseOptions.setDelegate(Delegate.GPU) 启用 GPU:
val baseOptions = BaseOptions.builder()
.setModelAssetPath("blaze_face_short_range.tflite") .setDelegate(Delegate.GPU) // 切换为 GPU .build()
val options = FaceDetector.FaceDetectorOptions.builder()
.setBaseOptions(baseOptions) .setRunningMode(RunningMode.IMAGE) .build()val detector = FaceDetector.createFromOptions(context, options)适用于:FaceDetector、FaceLandmarker、ObjectDetector、ImageClassifier。
8.3 LiteRT Interpreter GPU 配置
LiteRT 通过 GpuDelegate 启用 GPU,需先检查设备兼容性:
import org.tensorflow.lite.gpu.CompatibilityListimport org.tensorflow.lite.gpu.GpuDelegate
val compatList = CompatibilityList()val options = Interpreter.Options().apply {
if (compatList.isDelegateSupportedOnThisDevice) {
val delegateOptions = compatList.bestOptionsForThisDevice
addDelegate(GpuDelegate(delegateOptions))
} else { setNumThreads(4) setUseXNNPACK(true) // GPU 不可用时回退到 CPU + XNNPACK }}
val interpreter = Interpreter(modelFile, options)8.4 注意事项
- GPU delegate 必须在创建它的线程上使用,不可跨线程传递。
- 不是所有 TFLite ops 都支持 GPU,不支持的 op 会自动回退到 CPU(可能导致 CPU-GPU 同步开销)。
- int8 量化模型的 GPU 兼容性因设备而异。
efficientdet_lite0.tflite(int8)在部分设备上 GPU 推理可能失败,此时自动回退 CPU。 - 首次 GPU 推理较慢(需编译 shader),第二次起才能体现加速效果。benchmark 应排除首次 warmup。
- 内存:GPU delegate 会额外占用显存,在低端设备上注意 OOM。
8.5 GPU vs CPU 实测 Benchmark
测试设备:Android 手机 | 图片:含单张人脸的照片
时间:2026-04-08
========== GPU vs CPU Benchmark ==========
Module CPU GPU Speedup
------------------------------------------------------------
人脸检测 (BlazeFace) 27ms 18ms 1.50x特征点+情感 (FaceLandmarker) 30ms 22ms 1.36x人脸嵌入 (FaceNet-512) 63ms 45ms 1.40x物体检测 (EfficientDet) 33ms N/A -图像分类 (EfficientNet) 22ms 7ms 3.14x------------------------------------------------------------
TOTAL (comparable) 175ms 92ms 1.90x
Total analysis time: 353ms
Image quality: 75ms (algorithm only, no GPU)
==========================================
分析
| 模块 | CPU 耗时 | GPU 耗时 | 加速比 | 备注 |
|---|---|---|---|---|
| 人脸检测 (BlazeFace) | 27ms | 18ms | 1.50x | 模型极小(224KB),GPU 优势有限 |
| 特征点+情感 (FaceLandmarker) | 30ms | 22ms | 1.36x | 模型 3.6MB,GPU 加速稳定 |
| 人脸嵌入 (FaceNet-512) | 63ms | 45ms | 1.40x | 45MB 大模型,LiteRT GpuDelegate |
| 物体检测 (EfficientDet) | 33ms | N/A | - | int8 量化模型,设备 GPU 不兼容 |
| 图像分类 (EfficientNet) | 22ms | 7ms | 3.14x | float32 模型,GPU 加速最显著 |
| 可对比项合计 | 175ms | 92ms | 1.90x | 整体提速约 47% |
关键结论
- float32 模型受益最大:EfficientNet-Lite0(float32)GPU 加速达 3.14x。
- int8 量化模型兼容性差:EfficientDet-Lite0(int8)GPU 推理失败,回退到 CPU。如需 GPU 加速物体检测,应使用 float16 或 float32 版本。
- 小模型加速有限:BlazeFace(224KB)在 CPU 上已很快(27ms),GPU 的初始化和数据传输开销减少了加速效果。
- 综合推荐:对延迟敏感的场景建议开启 GPU(整体约 1.9x);对稳定性优先的场景可仅用 CPU + XNNPACK。
九、已知问题与注意事项
- ABI 兼容性: LiteRT 1.0.1 的 .so 支持
armeabi-v7a和arm64-v8a。在 x86 模拟器上可能报UnsatisfiedLinkError。 - 首次推理延迟: 模型首次加载需要时间(FaceNet ~500ms),建议 App 启动时预热。
- 内存占用: FaceNet-512 模型较大(45MB),在低内存设备上注意 OOM。可考虑 128 维版本。
- 线程安全: MediaPipe Task 对象不是线程安全的。如需多线程,每个线程创建独立实例。GPU delegate 同样有线程亲和性限制。
- Bitmap 格式: MediaPipe 要求
ARGB_8888格式的 Bitmap。BitmapFactory默认就是此格式。 - 预处理一致性: FaceNet 模型的预处理方式必须与训练时一致(见 4.3 节警告)。
- GPU 兼容性: int8 量化模型在部分设备 GPU 上不支持(如 EfficientDet-Lite0),会自动回退 CPU。
十、性能基准
CPU 模式
| 功能 | 模型 | 延迟 |
|---|---|---|
| 人脸检测 | BlazeFace short-range | 27ms |
| 特征点+Blendshapes | FaceLandmarker | 30ms |
| 人脸嵌入 | FaceNet-512 (XNNPACK) | 63ms |
| 物体检测 | EfficientDet-Lite0 int8 | 33ms |
| 图像分类 | EfficientNet-Lite0 float32 | 22ms |
| 图像质量 | Laplacian (纯算法) | 75ms |
| 综合分析(全部) | — | ~353ms |
GPU 加速模式
| 功能 | CPU 耗时 | GPU 耗时 | 加速比 |
|---|---|---|---|
| 人脸检测 | 27ms | 18ms | 1.50x |
| 特征点+Blendshapes | 30ms | 22ms | 1.36x |
| 人脸嵌入 | 63ms | 45ms | 1.40x |
| 物体检测 | 33ms | N/A (int8不兼容) | - |
| 图像分类 | 22ms | 7ms | 3.14x |
| 可对比项合计 | 175ms | 92ms | 1.90x |
详细分析见第八章 GPU 加速。
十一、模型下载 URL 汇总
# 人脸检测 (BlazeFace)curl -O https://storage.googleapis.com/mediapipe-models/face_detector/blaze_face_short_range/float16/latest/blaze_face_short_range.tflite
# 人脸特征点 + Blendshapescurl -O https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task
# 物体检测 (EfficientDet-Lite0, int8)curl -O https://storage.googleapis.com/mediapipe-models/object_detector/efficientdet_lite0/int8/1/efficientdet_lite0.tflite
# 图像分类 (EfficientNet-Lite0, float32)curl -O https://storage.googleapis.com/mediapipe-models/image_classifier/efficientnet_lite0/float32/1/efficientnet_lite0.tflite
# 人脸嵌入 (FaceNet-512) — 从 deepface 导出
# 来源: https://github.com/shubham0204/OnDevice-Face-Recognition-Android
curl -O https://github.com/shubham0204/OnDevice-Face-Recognition-Android/raw/main/app/src/main/assets/facenet_512.tflite十二、项目文件结构
app/src/main/
├── assets/
│ ├── blaze_face_short_range.tflite (224K)
│ ├── face_landmarker.task (3.6M)
│ ├── efficientdet_lite0.tflite (4.4M)
│ ├── efficientnet_lite0.tflite (18M)
│ └── facenet_512.tflite (45M)
├── java/com/example/facepptest/
│ ├── LiteRTManager.kt ← Facade
│ ├── MainActivity.kt
│ ├── BeautyScoreActivity.kt ← 综合分析
│ ├── FaceDetectActivity.kt
│ ├── FaceCompareActivity.kt
│ ├── FaceSearchActivity.kt
│ └── ml/
│ ├── MediaPipeFaceHelper.kt ← 人脸检测
│ ├── FaceLandmarkerHelper.kt ← 特征点+表情
│ ├── FaceEmbeddingHelper.kt ← FaceNet 嵌入
│ ├── ObjectDetectorHelper.kt ← 物体检测
│ ├── ImageClassifierHelper.kt ← 图像分类
│ ├── ImageQualityHelper.kt ← 质量评估
│ └── EmbeddingDbHelper.kt ← 向量存储
└── res/layout/...