You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google ML Kit文本识别:边界框与屏幕高度单位不匹配如何转换?

解决ML Kit文本识别坐标与屏幕像素不匹配的问题

核心问题在于:ML Kit返回的Line.getBoundingBox()坐标是输入图像坐标系下的像素值,而Resources.getSystem().getDisplayMetrics().heightPixels是设备屏幕的物理像素,二者属于不同坐标系,不能直接对比,和设备密度无关。

解决步骤

  1. 获取输入图像的实际尺寸
    你需要拿到ML Kit处理的那张图像的宽高(注意:如果是相机预览输入,要处理设备旋转带来的宽高交换,比如竖屏时相机预览帧的宽高会和屏幕方向相反)。
    比如使用CameraX时,可从ImageProxy中获取原始尺寸,再根据设备旋转角度调整:

    // 示例:处理CameraX图像的旋转适配
    int rotation = imageProxy.getImageInfo().getRotationDegrees();
    int inputImageWidth = imageProxy.getWidth();
    int inputImageHeight = imageProxy.getHeight();
    if (rotation == 90 || rotation == 270) {
        // 竖屏时交换宽高
        int temp = inputImageWidth;
        inputImageWidth = inputImageHeight;
        inputImageHeight = temp;
    }
    
  2. 编写坐标转换方法
    根据图像在屏幕上的显示模式(如fitCenter、centerCrop),计算图像到屏幕的缩放比例和偏移量,将图像坐标转换为屏幕坐标。以下是常见的fitCenter模式示例:

    /**
     * 将图像坐标系的Y坐标转换为屏幕坐标系的Y坐标
     * @param imageY 图像中的Y坐标
     * @param inputImageWidth 处理后的图像宽度(适配旋转后)
     * @param inputImageHeight 处理后的图像高度(适配旋转后)
     * @param screenWidth 屏幕宽度
     * @param screenHeight 屏幕高度
     * @return 屏幕坐标系下的Y坐标
     */
    private float convertImageYToScreenY(float imageY, int inputImageWidth, int inputImageHeight, int screenWidth, int screenHeight) {
        // 计算fitCenter模式下的缩放比例
        float scaleX = (float) screenWidth / inputImageWidth;
        float scaleY = (float) screenHeight / inputImageHeight;
        float scale = Math.min(scaleX, scaleY);
    
        // 计算图像在屏幕上显示的实际高度
        float displayedImageHeight = inputImageHeight * scale;
        // 计算垂直方向的偏移量(上下黑边的高度)
        float verticalOffset = (screenHeight - displayedImageHeight) / 2;
    
        // 转换坐标:图像Y缩放后加上偏移量
        return imageY * scale + verticalOffset;
    }
    
  3. 修改文本识别逻辑
    在读取文本行时,先将图像坐标转换为屏幕坐标,再进行区域判断:

    private void readLines(Text text, int inputImageWidth, int inputImageHeight, int screenWidth, int screenHeight){
        if (text != null) {
            for (TextBlock block : text.getTextBlocks()) {
                for (Line line : block.getLines()) {
                    float imageCenterY = line.getBoundingBox().centerY();
                    float screenCenterY = convertImageYToScreenY(imageCenterY, inputImageWidth, inputImageHeight, screenWidth, screenHeight);
                    if (checkArea(screenCenterY, screenHeight)) {
                        doSomething(line.getText());
                    }
                }
            }
        }
    }
    
    private boolean checkArea(float center, int screenHeight){
        float lowerBound = screenHeight / 3f;
        float upperBound = (screenHeight / 3f) * 2;
        return center > lowerBound && center < upperBound;
    }
    

关键注意事项

  • 如果你的预览布局是centerCrop模式,缩放比例要取Math.max(scaleX, scaleY),并重新计算偏移量。
  • 确保输入图像的尺寸是ML Kit实际处理的图像尺寸,不要使用预览控件的尺寸(预览控件可能被拉伸)。

内容的提问来源于stack exchange,提问作者K.E.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 23:22:49