如何在Flutter中用Google ML Kit从收据识别结果过滤商品名称?
从OCR收据文本中提取商品名称的方法
以下是几种实用的过滤方案,可根据收据格式灵活组合:
基于文本模式匹配
超市收据的商品行通常遵循固定格式,比如「商品名 数量 单价 总价」或「商品名 总价」。可以用正则表达式匹配这类行,提取商品名部分:// 匹配「商品名 数量 单价 总价」格式的行 final itemPattern = RegExp(r'^(.+?)\s+\d+\s+\d+\.\d+\s+\d+\.\d+$'); // 匹配简化版「商品名 总价」格式 final simpleItemPattern = RegExp(r'^(.+?)\s+\d+\.\d+$');遍历OCR得到的文本列表,对每行做匹配,同时排除标题、小计、日期等非商品行:
final excludeKeywords = ['小计', '总计', '日期', '收银', 'ITEM', 'TOTAL', 'DATE']; List<String> extractItems(List<String> textList) { final items = <String>[]; for (final line in textList) { // 跳过排除关键词的行 if (excludeKeywords.any(keyword => line.contains(keyword))) continue; // 尝试匹配两种模式 final match = itemPattern.firstMatch(line) ?? simpleItemPattern.firstMatch(line); if (match != null) { items.add(match.group(1)!.trim()); } } return items; }基于上下文范围筛选
商品明细一般集中在「商品列表」和「小计」之间的区域,先定位分界行,再提取中间内容:List<String> extractItemsByContext(List<String> textList) { final items = <String>[]; // 找到商品区域的起始和结束位置 final startIdx = textList.indexWhere((line) => line.contains('商品明细') || line.contains('ITEMS')); final endIdx = textList.indexWhere((line) => line.contains('小计') || line.contains('SUBTOTAL')); if (startIdx != -1 && endIdx != -1 && startIdx < endIdx) { // 提取中间行并过滤非商品内容 final candidateLines = textList.sublist(startIdx + 1, endIdx); for (final line in candidateLines) { // 排除纯数字行、过短行 if (RegExp(r'^\d+$').hasMatch(line) || line.length < 2) continue; items.add(line.trim()); } } return items; }商品名清洗优化
提取到的原始内容可能带有数字、符号残留,需要进一步清洗:String cleanItemName(String rawName) { // 移除数字、货币符号及特殊字符,保留中英文和空格 return rawName.replaceAll(RegExp(r'[\d\$¥%*]'), '').trim(); }进阶方案:文本分类模型
如果收据格式差异极大,正则和规则无法覆盖,可以集成轻量TensorFlow Lite文本分类模型,对每行文本做「商品/非商品」分类。可利用开源收据数据集训练模型,或对预训练文本分类模型微调后在Flutter中部署。
内容的提问来源于stack exchange,提问作者Prabin Maharjan
相关产品推荐
相关产品推荐

