Android平台Vuforia文本识别:点击识别框获取对应文字的实现问题
实现Vuforia文本识别矩形框点击获取对应文字
看起来你已经走了一大步——成功跑通Vuforia的文本识别示例,现在就差最后一步把触摸操作和识别文字关联起来了。我来帮你把逻辑补全:
第一步:给WordDesc类添加屏幕坐标矩形字段
首先,你需要让WordDesc能存储文字对应的屏幕坐标系矩形,因为Vuforia返回的是世界坐标,得转换成Android触摸系统能用的屏幕坐标:
public class WordDesc { private String text; // 识别出的文字内容 private RectF screenRect; // 文字对应的屏幕包围矩形 // 补全构造方法、getter和setter public String getText() { return text; } public void setText(String text) { this.text = text; } public RectF getScreenRect() { return screenRect; } public void setScreenRect(RectF screenRect) { this.screenRect = screenRect; } }
第二步:将Vuforia识别的文字坐标转为屏幕坐标
在你获取Vuforia文本识别结果的回调方法里(比如onTextRecognized),需要把文字的世界坐标转换成Android屏幕坐标,并存入WordDesc:
// 假设从Vuforia的TextRecoResult拿到当前识别的文字列表 List<TextRecoResult.Word> vuforiaWords = textRecoResult.getWords(); wordDescList.clear(); int screenWidth = getResources().getDisplayMetrics().widthPixels; int screenHeight = getResources().getDisplayMetrics().heightPixels; CameraCalibration camCalib = CameraDevice.getInstance().getCameraCalibration(); for (TextRecoResult.Word vuforiaWord : vuforiaWords) { WordDesc wordDesc = new WordDesc(); wordDesc.setText(vuforiaWord.getText()); // 转换文字的四个顶点到屏幕坐标 List<Vec2F> worldVertices = vuforiaWord.getVertices(); float[] screenPoints = new float[worldVertices.size() * 2]; for (int i = 0; i < worldVertices.size(); i++) { Vec2F worldPoint = worldVertices.get(i); // 用Vuforia Renderer把世界坐标转成0-1范围的归一化屏幕坐标 Vec2F normalizedScreenPoint = Renderer.getInstance().convert2DPoint(camCalib, worldPoint); // 转成实际像素坐标,同时调整Y轴方向(Android触摸Y轴从上到下,Vuforia是从下到上) screenPoints[2*i] = normalizedScreenPoint.getData()[0] * screenWidth; screenPoints[2*i+1] = screenHeight - normalizedScreenPoint.getData()[1] * screenHeight; } // 从屏幕点中计算包围矩形的最小/最大X、Y值 float minX = Float.MAX_VALUE, maxX = Float.MIN_VALUE; float minY = Float.MAX_VALUE, maxY = Float.MIN_VALUE; for (int i = 0; i < screenPoints.length; i += 2) { minX = Math.min(minX, screenPoints[i]); maxX = Math.max(maxX, screenPoints[i]); minY = Math.min(minY, screenPoints[i+1]); maxY = Math.max(maxY, screenPoints[i+1]); } // 将构建好的矩形设置到WordDesc中 wordDesc.setScreenRect(new RectF(minX, minY, maxX, maxY)); wordDescList.add(wordDesc); }
第三步:完善触摸点击的判断逻辑
回到你已经写了一部分的触摸事件代码,只需要遍历wordDescList,判断触摸点是否落在某个文字的屏幕矩形内即可:
float X = event.getRawX(); // 获取屏幕触摸点坐标 float Y = event.getRawY(); // 获取屏幕触摸点坐标 if (wordDescList != null && wordDescList.size() > 0) { for (WordDesc wordDesc : wordDescList) { RectF rect = wordDesc.getScreenRect(); // 检查触摸点是否在当前文字的矩形范围内 if (rect != null && rect.contains(X, Y)) { // 成功获取到点击的文字 String clickedText = wordDesc.getText(); // 这里可以做你需要的后续操作,比如弹Toast、传递给其他组件 Toast.makeText(this, "你点击了:" + clickedText, Toast.LENGTH_SHORT).show(); break; // 找到第一个匹配的文字就退出循环,避免重叠文字的干扰 } } }
小提示
- 如果出现矩形绘制和触摸判断错位的情况,大概率是Y轴方向没调整对,记得确认
screenHeight - normalizedScreenPoint.getData()[1] * screenHeight这一步是否正确。 - 如果有重叠的文字,你可以根据需求调整判断逻辑(比如取绘制层级最上层的文字,这时候可能需要利用Vuforia返回的文字层级信息,或者自己维护绘制顺序)。
内容的提问来源于stack exchange,提问作者prakash mayane
相关产品推荐
相关产品推荐

