基于Pytesseract的驾驶证数据提取正则表达式问题与优化
驾驶证OCR信息提取优化方案
优化说明
- 简化冗余正则逻辑,使用
re.IGNORECASE参数省略大小写匹配规则 - 兼容OCR识别误差,包含拼写偏差(如
Issue/Iseue、Validity/falidity)、特殊符号干扰等场景 - 新增签发日期、非营运有效期、营运有效期三个字段的提取逻辑
- 兼容两种常见OCR输出格式,包含样本中
N:开头的姓名行场景
优化后完整代码
import pytesseract import cv2 import re import numpy as np import datetime from PIL import Image def driver_license(filename): """ 处理驾驶证图像OCR,提取核心信息 """ # 图像角度校正 img = cv2.imread(filename) osd_info = pytesseract.image_to_osd(img) rotate_angle = int(re.search('(?<=Rotate: )\d+', osd_info).group(0)) if rotate_angle != 0: pil_img = Image.open(filename) pil_img = pil_img.rotate(360 - rotate_angle, expand=True) pil_img.save(filename) # 图像预处理 img = cv2.imread(filename) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) kernel = np.ones((1, 1), np.uint8) processed_img = cv2.dilate(cv2.erode(gray, kernel, iterations=1), kernel, iterations=1) # OCR识别 ocr_text = pytesseract.image_to_string(processed_img) lines = [line.strip() for line in ocr_text.split('\n') if line.strip()] # 初始化返回结果 result = { 'firstName': None, 'lastName': None, 'age': None, 'documentNumber': None, 'issue_date': None, 'validity_nt': None, 'validity_t': None } for idx, line in enumerate(lines): try: # 提取姓名:兼容Name开头和N开头两种格式 if re.search(r'(name|^N\s*:)', line, re.IGNORECASE): clean_name = re.sub(r'[^a-zA-Z\s]', '', line) clean_name = re.sub(r'name', '', clean_name, flags=re.IGNORECASE).strip() name_parts = clean_name.split() if len(name_parts) >= 2: result['firstName'] = ' '.join(name_parts[:-1]) result['lastName'] = name_parts[-1] # 兼容姓名在当前行下一行的场景 elif not result['firstName'] and idx + 1 < len(lines): next_line = re.sub(r'[^a-zA-Z\s]', '', lines[idx+1]).strip() name_parts = next_line.split() result['firstName'] = ' '.join(name_parts[:-1]) result['lastName'] = name_parts[-1] # 提取驾驶证编号:合并两种格式规则 doc_match = re.search(r'[A-Z]{2}[-\s]?\d{13}', line, re.IGNORECASE) if doc_match: result['documentNumber'] = re.sub(r'[^A-Z0-9]', '', doc_match.group(), flags=re.IGNORECASE) # 提取年龄 if re.search(r'DOB', line, re.IGNORECASE): year_match = re.search(r'\d{4}', line) if year_match: result['age'] = datetime.datetime.now().year - int(year_match.group()) # 提取签发日期:兼容拼写错误 if re.search(r'I\w*e\s+Date', line, re.IGNORECASE): date_match = re.search(r'\d{2}/\d{2}/\d{4}', line) if date_match: result['issue_date'] = date_match.group() # 提取有效期:兼容OCR识别误差 if re.search(r'(validity|falidity)\s*\(NT\)', line, re.IGNORECASE): date_match = re.search(r'(\d{2}/\d{2}/\d{4}|\d{4})', line) if date_match: result['validity_nt'] = date_match.group() if re.search(r'(validity|falidity)\s*\(T\)', line, re.IGNORECASE): val_content = line.split(':', 1)[-1].strip() if ':' in line else line result['validity_t'] = re.sub(r'[^A-Z0-9/]', '', val_content).strip() except Exception: continue return result
正则表达式简易学习指南
- 核心基础优先掌握:先记住常用元字符含义,
\d匹配数字、\s匹配空白符、.匹配任意字符、*/+匹配重复次数、()用于分组提取需要的内容、[]用于匹配指定字符范围 - 常用参数掌握:
re.IGNORECASE忽略大小写、re.MULTILINE多行匹配,两个参数可以覆盖绝大多数日常场景 - OCR场景匹配技巧:因为OCR存在识别误差,不用追求100%精准匹配关键词,比如匹配签发日期可以用
I\w*e\s+Date,兼容中间字符识别错误的情况,优先提取后续符合格式的日期内容 - 练习方法:从固定格式的文本匹配练手,比如先练习匹配手机号、邮箱、日期,再逐步处理有识别误差的非标准化文本
内容的提问来源于stack exchange,提问作者senarijit1618
相关产品推荐
相关产品推荐

