如何强制 Android 版 Mobile Vision 读取整行文本
Posted
技术标签:
【中文标题】如何强制 Android 版 Mobile Vision 读取整行文本【英文标题】:How to force Mobile Vision for Android to read full lines of text 【发布时间】:2017-07-10 13:32:59 【问题描述】:我按照教程实现了适用于 android 的 Google Mobile Vision。我正在尝试构建一个应用程序来扫描收据并查找数字总数。但是,当我扫描以不同格式打印的不同收据时,API 将以任意方式检测 TextBlocks。例如,在一张收据中,如果几个文本单词由单个空格分隔,那么它们将被分组到一个 TextBlock 中。但是,如果文本的两个单词被很多空格分隔,那么即使它们出现在同一“行”上,它们也会被分隔为独立的 TextBlock。我想要做的是强制 API 将收据的每一行识别为一个实体。这可能吗?
【问题讨论】:
您找到解决方案了吗?如果是这样,您是否能够在现有图像上检测而不是实时使用相机应用程序? 您找到解决方案了吗? 【参考方案1】:public ArrayList<T> getAllGraphicsInRow(float rawY)
synchronized (mLock)
ArrayList<T> row = new ArrayList<>();
// Get the position of this View so the raw location can be offset relative to the view.
int[] location = new int[2];
this.getLocationOnScreen(location);
for (T graphic : mGraphics)
float rawX = this.getWidth();
for (int i=0; i<rawX; i+=10)
if (graphic.contains(i - location[0], rawY - location[1]))
if(!row.contains(graphic))
row.add(graphic);
return row;
这应该在 GraphicOverlay.java 文件中,并且本质上会获取该行中的所有图形。
public static boolean almostEqual(double a, double b, double eps)
return Math.abs(a-b)<(eps);
public static boolean pointAlmostEqual(Point a, Point b)
return almostEqual(a.y,b.y,10);
public static boolean cornerPointAlmostEqual(Point[] rect1, Point[] rect2)
boolean almostEqual=true;
for (int i=0; i<rect1.length;i++)
if (!pointAlmostEqual(rect1[i],rect2[i]))
almostEqual=false;
return almostEqual;
private boolean onTap(float rawX, float rawY)
String priceRegex = "(\\d+[,.]\\d\\d)";
ArrayList<OcrGraphic> graphics = mGraphicOverlay.getAllGraphicsInRow(rawY);
OcrGraphic currentGraphics = mGraphicOverlay.getGraphicAtLocation(rawX,rawY);
if (graphics !=null && currentGraphics!=null)
List<? extends Text> currentComponents = currentGraphics.getTextBlock().getComponents();
final Pattern pattern = Pattern.compile(priceRegex);
final Pattern pattern1 = Pattern.compile(priceRegex);
TextBlock text = null;
Log.i("text results", "This many in the row: " + Integer.toString(graphics.size()));
ArrayList<Text> combinedComponents = new ArrayList<>();
for (OcrGraphic graphic : graphics)
if (!graphic.equals(currentGraphics))
text = graphic.getTextBlock();
Log.i("text results", text.getValue());
combinedComponents.addAll(text.getComponents());
for (Text currentText : currentComponents) // goes through components in the row
final Matcher matcher = pattern.matcher(currentText.getValue()); // looks for
Point[] currentPoint = currentText.getCornerPoints();
for (Text otherCurrentText : combinedComponents) //Looks for other components that are in the same row
final Matcher otherMatcher = pattern1.matcher(otherCurrentText.getValue()); // looks for
Point[] innerCurrentPoint = otherCurrentText.getCornerPoints();
if (cornerPointAlmostEqual(currentPoint, innerCurrentPoint))
if (matcher.find()) // if you click on the price
Log.i("oh yes", "Item: " + otherCurrentText.getValue());
Log.i("oh yes", "Value: " + matcher.group(1));
itemList.add(otherCurrentText.getValue());
priceList.add(Float.valueOf(matcher.group(1)));
if (otherMatcher.find()) // if you click on the item
Log.i("oh yes", "Item: " + currentText.getValue());
Log.i("oh yes", "Value: " + otherMatcher.group(1));
itemList.add(currentText.getValue());
priceList.add(Float.valueOf(otherMatcher.group(1)));
Toast toast = Toast.makeText(this, " Text Captured!" , Toast.LENGTH_SHORT);
toast.show();
return true;
return false;
这应该在 OcrCaptureActivity.java 中,它将 TextBlock 分成几行,并在与该行相同的行中查找块并检查组件是否都是价格,并相应地打印所有值。
earlyEqual 中的 eps 值是它检查行中图形高度的容差。
【讨论】:
我认为这只适用于实时使用相机应用程序而不是现有图像,因为您需要使用文本识别 API 的类 CameraSourcePreview 和 GraphicOverlay,对吗?以上是关于如何强制 Android 版 Mobile Vision 读取整行文本的主要内容,如果未能解决你的问题,请参考以下文章
Timeline Vis - 使用子组排序强制子组 2 在子组 1 之后
install ubuntu on Android mobile phone