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
相关产品推荐
相关产品推荐

