Google ML Kit文本识别:边界框与屏幕高度单位不匹配如何转换?
解决ML Kit文本识别坐标与屏幕像素不匹配的问题
核心问题在于:ML Kit返回的Line.getBoundingBox()坐标是输入图像坐标系下的像素值,而Resources.getSystem().getDisplayMetrics().heightPixels是设备屏幕的物理像素,二者属于不同坐标系,不能直接对比,和设备密度无关。
解决步骤
获取输入图像的实际尺寸
你需要拿到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; }编写坐标转换方法
根据图像在屏幕上的显示模式(如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; }修改文本识别逻辑
在读取文本行时,先将图像坐标转换为屏幕坐标,再进行区域判断: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.
相关产品推荐
相关产品推荐

