原生Android开发类Lenskart眼镜试戴功能的最佳实现方案咨询
原生Android实现类Lenskart眼镜虚拟试戴落地方案
你选CameraX做相机底座是对的,比直接实现Camera2少踩80%的生命周期、设备适配坑,整套实现走下来不需要接重型商用SDK,离线就能跑,实时性和精度都能到商用标准,具体路径如下:
核心技术栈选型
- 相机层:CameraX 承载预览、实时帧分析、拍照全流程,不用自己处理不同厂商机型的相机兼容问题
- 人脸关键点检测:用ML Kit的人脸网格检测能力,离线运行,中端机上单帧检测耗时稳定在10-20ms,能直接输出左右眼内外眼角、瞳孔、鼻梁、人脸转角/倾斜角等核心数据,精度足够支撑眼镜叠加
- 渲染层:如果只做2D静态眼镜素材,用自定义View叠加在PreviewView上做画布绘制即可;如果要做带光影、半透镜片效果的3D素材,直接用OpenGL ES做图层渲染,延迟更低
分步实现路径
1. 相机基础能力搭建
- 引入CameraX依赖后,依次绑定三个核心用例:
Preview:绑定PreviewView做实时预览,分辨率选1280*720即可,过高分辨率会拖慢后续检测速度ImageAnalysis:设置为非阻塞模式,输出YUV_420_888格式的实时帧,单独开分析线程跑人脸检测,不要占主线程ImageCapture:配置高分辨率输出,用于后续试戴拍照的素材合成
- 注意提前申请CAMERA权限,前后置摄像头切换时要同步更新检测的旋转角度、镜像配置。
2. 关键点坐标映射(最容易出问题的环节)
- 把ImageAnalysis输出的实时帧转换成ML Kit要求的InputImage格式,传入人脸检测器,检测器要提前开启轮廓检测、分类检测、人脸三维角度检测的开关,不然拿不到需要的点位。
- 拿到检测结果后,不要直接用返回的像素坐标画素材:ML Kit返回的坐标是基于分析帧的像素坐标系,和PreviewView的显示坐标系存在缩放、裁剪、旋转的差值,直接用必然错位。直接用CameraX自带的
MeteringPointFactory做坐标转换,把帧上的关键点映射到PreviewView的实际显示位置,不用自己手写矩阵转换,适配所有预览缩放模式。 - 核心要提取的锚点:左右眼外眼角、左右眼内眼角、鼻梁中点、人脸侧倾角(roll)、左右转头角度(yaw)。
3. 眼镜素材精准叠加
- 尺寸适配:以左右外眼角的直线距离为基准,按照「双眼外眼角间距占眼镜素材总宽度90%」的比例缩放素材,适配不同脸宽、不同距离下的素材大小
- 角度适配:根据人脸侧倾的roll值,用Matrix对素材做对应角度的旋转,保证歪头时眼镜和人脸角度一致
- 透视适配:根据左右转头的yaw值,对素材做水平方向的线性压缩,比如转头30度时素材宽度压缩到原有的70%,模拟近大远小的透视效果,避免素材看起来像浮在屏幕上
- 防抖处理:加一个简单的低通滤波,每次更新点位时取当前点位和上一帧点位的加权平均值,避免关键点轻微抖动导致眼镜跳来跳去,阈值设为0.2左右体验就很顺滑。
4. 拍照合成
- 不要直接截取预览屏当最终照片,分辨率太低。触发拍照时,先拿到ImageCapture输出的高分辨率原始帧,按照和预览层同比例的坐标映射规则,把眼镜素材画到高分辨率Bitmap上再保存,输出的成片清晰度和原生相机拍照一致。
常见坑点避坑
- 别用系统原生的FaceDetector做检测,只能返回人脸大致范围,拿不到精准的眼部点位,叠加误差能到半张脸大
- 前置摄像头一定要做坐标镜像处理,不然画出来的眼镜左右是反的,和用户实际视角不符
- 人脸置信度低于0.7的时候直接隐藏素材,避免半张脸、人脸出框时素材乱飘
- 中低端机上把检测帧率降到20fps就行,不用硬上30fps,不然容易发热掉帧
- 透明PNG素材提前做屏幕密度适配,不要拿一张4K图全局缩放,浪费内存还容易OOM
内容的提问来源于stack exchange,提问作者Ashish Gautam
相关产品推荐
相关产品推荐

