Android使用Google Vision API在实时相机预览上绘制人脸landmark的缩放适配问题
实时相机预览场景下面部Landmark坐标适配方法
问题现状
- 已实现功能:可在实时相机预览界面正确绘制人脸边界框(bounding box),依赖项目内置的
translateX/translateY/scaleX/scaleY方法完成传感器坐标系到预览画布坐标系的映射。 - 现存异常:绘制面部landmark关键点时直接使用检测返回的原始坐标,未经过对应坐标转换,导致绘制位置存在明显偏移。
- 适配障碍:网络参考的静态Bitmap场景缩放逻辑,仅适用于无旋转、无裁剪、无镜像的静态图像预览,无法直接套用在带动态预览参数的实时相机场景中。
偏移根因
当前代码中人边界面框能正确对齐,本质是复用了适配实时预览的专属坐标转换方法完成了坐标系映射;而landmark的原始坐标和人脸边界框的原始坐标同属相机传感器输出的原始图像参考系,直接使用未转换的坐标值,自然会和预览画面存在错位。
正确适配逻辑
不需要重新计算静态图场景下的通用缩放值,直接复用现有为bbox服务的同一套坐标转换规则即可:
- 对landmark的原始x坐标,传入
translateX完成横向预览偏移/镜像校正,得到画布上的对应x位置 - 对landmark的原始y坐标,传入
translateY完成纵向预览偏移校正,得到画布上的对应y位置
不需要套用静态图的Math.min(viewWidth/imageWidth, viewHeight/imageHeight)计算逻辑——这套逻辑没有覆盖实时相机场景必须处理的传感器方向旋转、前置摄像头镜像、预览裁剪留边等动态参数,而项目已封装的坐标转换方法已经把这些补偿逻辑全部内置,只要bbox绘制准确,同参考系的landmark坐标经过同一套转换后必然能对齐。
修正后的绘制代码
替换原有landmark绘制循环的代码段:
for (Landmark landmark : face.getLandmarks()) { // 复用bbox同款坐标转换逻辑,替换直接取原始坐标的写法 float cx = translateX(landmark.getPosition().x); float cy = translateY(landmark.getPosition().y); canvas.drawCircle(cx, cy, 10, paint); }
内容的提问来源于stack exchange,提问作者ReeceG
相关产品推荐
相关产品推荐

