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

Flutter名片扫描应用问题求助:信息提取与字段显示异常

名片扫描识别优化方案

针对你遇到的信息提取不准确、字段映射失效问题,从OCR配置、正则优化、提取逻辑三方面给出解决方案:

一、提升OCR识别精度

flutter_tesseract_ocr默认仅支持英语识别,你的名片属于法语体系,需添加多语言支持并设置合适的页面分割模式,提升识别连贯性:

final text = await FlutterTesseractOcr.extractText(
  imagePath,
  language: 'fra+eng', // 适配法语+英语双语名片
  args: {
    '--psm': '6', // 假设名片为单一文本块,优化识别效率
  },
);

二、修复各字段提取逻辑

替换原有的提取函数,适配法语名片的格式特征:

1. 姓名提取(支持中间名、连字符)

String extractName(String text) {
  // 匹配首字母大写的姓名行(支持空格、连字符分隔)
  final namePattern = RegExp(r'^[A-Z][a-z]+(?:[\s-][A-Z][a-z]+)+$', multiLine: true);
  final matches = namePattern.allMatches(text);
  if (matches.isNotEmpty) {
    return matches.first.group(0)!;
  }
  return '';
}

2. 职位提取(适配法语职位关键词)

String extractFunction(String text, String name) {
  final lines = text.split('\n').map((line) => line.trim()).where((line) => line.isNotEmpty).toList();
  final nameLineIndex = lines.indexWhere((line) => line.contains(name));
  
  // 优先取姓名行的下一行作为职位,排除无效行
  if (nameLineIndex != -1 && nameLineIndex < lines.length - 1) {
    final candidate = lines[nameLineIndex + 1];
    if (!candidate.contains(RegExp(r'@|\d{5}|SA|SARL'))) {
      return candidate;
    }
  }
  
  // 备用逻辑:匹配包含法语职位关键词的行
  final jobKeywords = ['Directeur', 'Ingénieur', 'Manager', 'Chargé', 'Responsable'];
  for (var line in lines) {
    if (jobKeywords.any((kw) => line.contains(kw))) {
      return line;
    }
  }
  return '';
}

3. 公司提取(识别法语公司后缀)

String extractSociete(String text) {
  final lines = text.split('\n').map((line) => line.trim()).where((line) => line.isNotEmpty).toList();
  // 匹配包含法国常见公司后缀的行
  final companyPattern = RegExp(r'.*(SA|SARL|Inc\.|Ltd\.|Groupe).*', caseSensitive: false);
  for (var line in lines) {
    if (companyPattern.hasMatch(line)) {
      return line;
    }
  }
  // 备用逻辑:取大写开头的非姓名行
  for (var line in lines) {
    if (line.startsWith(RegExp(r'[A-Z]')) && !extractName(text).contains(line)) {
      return line;
    }
  }
  return '';
}

4. 地址提取(匹配法国邮编+城市格式)

String extractAdresse1(String text) {
  // 匹配包含门牌号、街道的行
  final addressPattern = RegExp(r'^\d+\s+[A-Za-z\s]+$', multiLine: true);
  final match = addressPattern.firstMatch(text);
  if (match != null) {
    return match.group(0)!;
  }
  return '';
}

String extractAdresse2(String text) {
  // 匹配法国5位邮编+城市格式
  final cityPattern = RegExp(r'\d{5}\s+[A-Za-z\s]+', multiLine: true);
  final match = cityPattern.firstMatch(text);
  if (match != null) {
    return match.group(0)!;
  }
  return '';
}

5. 手机号提取(支持国际号码格式)

String extractNumero(String text) {
  final phonePattern = RegExp(r'[+]?[(]?[0-9]{1,4}[)]?[-\s\./0-9]{8,}');
  final matches = phonePattern.allMatches(text);
  if (matches.isNotEmpty) {
    // 清理非数字和+的冗余字符
    return matches.first.group(0)!.replaceAll(RegExp(r'[^\d+]'), '');
  }
  return '';
}

6. 邮箱提取(通用正则)

String extractEmail(String text) {
  final emailPattern = RegExp(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}');
  final match = emailPattern.firstMatch(text);
  if (match != null) {
    return match.group(0)!;
  }
  return '';
}

7. 网址提取(支持http/https/www前缀)

String extractWebsite(String text) {
  final websitePattern = RegExp(r'(https?:\/\/)?(www\.)?[a-zA-Z0-9-]+\.[a-zA-Z]{2,}(?:\/[^\s]*)?');
  final match = websitePattern.firstMatch(text);
  if (match != null) {
    var url = match.group(0)!;
    // 补全http前缀(如果缺失)
    if (!url.startsWith('http')) {
      url = 'https://$url';
    }
    return url;
  }
  return '';
}

三、清理冗余代码

删除不必要的变量和onChanged逻辑(TextEditingController已保存输入值):

// 移除以下冗余变量
// String name = '';
// String function = '';
// String number = '';
// String website = '';

// 同时移除TextFormField的onChanged回调(除非需要实时处理输入)
// 例如原姓名字段的onChanged可直接删除,saveForm直接读取controller.text即可

四、验证字段映射

extractInformation函数的赋值逻辑本身是正确的,只要提取函数返回有效值,对应输入字段就会正确显示内容。


内容的提问来源于stack exchange,提问作者GreatGig

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 08:22:06