基于OCR的身份证信息提取

背景

用户上传的身份证照片各式各样,图像质量参差不齐,部分还存在水印,并且混杂身份证的正反面,这就导致在OCR识别过程中难度比较大。

针对于此,进行图像预处理的各种尝试,大方向是将图像中的身份证框出来进行裁剪,让输入给OCR进行识别的图像尽可能质量好。

尝试过如下方法:

1.利用opencv进行框选

该方案由于图像大小、分辨率、背景区别差异大,效果不好

2.利用rembg算法进行抠图

由于rembg算法是扣人像的,在身份证照片特别突出的情况下,容易被扣掉身份信息

3.利用YOLO目标检测算法进行检测,识别率高

步骤为:

0.按照如下文件结构构建

our_project

—/images

——/train

——/val

—/labels

——/train

——/val

—detect_data.yaml

1
2
3
4
5
6
7
#训练图片目录以及类别
names:
0: id_card
path: D:\0000_Work\python_project\ocr\YOLO_segement
train: images/train
val: images/val

1.安装相应的python库

2.训练模型指令

https://docs.ultralytics.com/zh/tasks/detect/#dataset-format

yolo detect train data=data-detect.yaml model=yolo11n.pt epochs=100 imgsz=640

3.模型评估并导出onnx模型,onnx模型为跨平台的模型参数文件,可直接跨平台加载。

1
2
3
4
5
from ultralytics import YOLO
model = YOLO('runs/detect/train/weights/best.pt')
model.val()
#导出onnx模型
model.export(format='onnx')

4.OCR识别

在OCR识别之前尽量将身份证照片正向摆正进行OCR识别。

其中最终OCR识别之前的图像预处理步骤为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
def preprocess_id_card(pt_path ,image_path ,save_dir="YOLO_id_cards",):
"""完整的身份证图像预处理流程"""
image = cv2.imread(image_path)
if image is None:
logger.info(f"无法读取图像:{image_path}")
return None

# Step 1: 使用YOLO检测并裁剪去背景
# YOLO身份证识别&裁剪
no_bg = cut(pt_path, image_path)
if no_bg is None:
return None

# Step 2: 检测四个角点并透视矫正
corners = detect_id_card_corners(no_bg)
if corners is None:
logger.info(f"[{os.path.basename(image_path)}] ⚠️ 无法检测身份证角点")
return None
corrected = perspective_transform(no_bg, corners)

# Step 3: 如果为竖图则旋转90度(人脸朝上)
corrected = rotate_if_vertical(corrected)

# Step 4: OCR判断是否180度倒置
# 对透视矫正后的图像先OCR识别,判断是否倒置180度
ocr_results = ocr_(corrected) # 你需要支持传入图像(cv2 image)或者保存临时图像后传路径
if ocr_results:
img_h, img_w = corrected.shape[:2]
if is_id_card_upside_down(ocr_results):
print("检测到身份证倒置180度,自动旋转180度")
logger.info("检测到身份证倒置180度,自动旋转180度")
corrected = cv2.rotate(corrected, cv2.ROTATE_180)
#show(image_path, corrected)
else:
logger.info("OCR未检测到关键字段,默认身份证正向")

# show("透视矫正后", corrected)
# ✅ 使用 PaddleOCR 自动旋转
#aligned = align_face_after_perspective(corrected)
# 根据长宽比判断是否旋转90度(人脸朝上)
#corrected = auto_rotate_image_with_paddle(corrected)
#aligned = correct_idcard_orientation(corrected)
corrected = enhance_for_address_recognition(corrected)
# 保存图像
# Step 5: 保存矫正后的图像
os.makedirs(save_dir, exist_ok=True)
base_name = os.path.basename(image_path)
name_no_ext, ext = os.path.splitext(base_name)
save_path = os.path.join(save_dir, f"{name_no_ext}_corrected{ext}")
cv2.imwrite(save_path, corrected)
logger.info(f"✅ 图像保存到: {save_path}")

return save_path

OCR识别代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def ocr_path(image_path):
ocr = PaddleOCR(use_angle_cls=True, lang='ch',
# rec_model_dir='ch_PP-OCRv5/PP-OCRv5_server_rec_infer',
ocr_version='PP-OCRv4'
)
img = cv2.imread(image_path)
if img is None:
return None
result = ocr.ocr(img, cls=True)
if not result or not result[0]:
return None
logger.info(f"ocr识别结果:{result}")
print(result)

return result

5.OCR识别后处理:地址信息清洗

整体代码流程为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

# 示例调用方式:
if __name__ == '__main__':
# 加载YOLO模型
pt_path = 'detect_best.onnx'
# 加载图片进行推理(判断准确率用)
image_dir = 'D:/0000_Work/python_project/ocr/utils/download_image/data/images_all'
#image_dir = 'D:/0000_Work/python_project/ocr/idCardHandler/image1'
#point(image_dir, output_dir, pt_path)
#batch_cut(pt_path="detect_best.onnx",input_dir="input_images",output_dir="cropped_results")
# image_dir = "D:/0000_Work/ai/identification_img/"
files = get_file_names(image_dir)

results = [] # 保存每张图片的文件名和地址信息
for file in files:
image_path = os.path.join(image_dir, file)
logger.info(f"开始处理:{image_path}")

# Step 1: 身份证图像预处理
save_path = preprocess_id_card(pt_path, image_path)

if save_path is None:
logger.error(f"❌ 身份证预处理失败,跳过 OCR:{image_path}")
continue

# save_path = crop_address(save_path)
ocr_results = ocr_path(save_path)
# Step 2: OCR识别
try:
ocr_results = ocr_path(save_path)
except Exception as e:
logger.exception(f"OCR处理异常:{e}")
ocr_results = []

raw_addr = ""
if not ocr_results:
print("---------------ocr_results--------------")
print(ocr_results)
logger.warning(f"[{os.path.basename(save_path)}] ⚠️ OCR识别结果为空")
print(f"[{os.path.basename(save_path)}] ⚠️ OCR识别结果为空")
raw_addr = ""
else:
raw_addr = extract_full_address(ocr_results)
logger.info(f"原始地址文本: {raw_addr}")
print("原始地址文本:", raw_addr)

# Step 3: 地址清洗和结构化
parsed = clean_and_parse_address(raw_addr)
print("结构化解析结果:", parsed)
print("\n")

results.append({
"文件名": file,
"地址": parsed.get('full_address', ''),
"ocr_results": ocr_results
})

# Step 4: 保存结果为 Excel
# 保存为 Excel
df = pd.DataFrame(results)
output_excel_path = "YOLO_身份证地址提取结果_V5.xlsx"
df.to_excel(output_excel_path, index=False)
logger.info(f"🎉 地址信息已保存至 Excel:{output_excel_path}")

觉得不错的话,支持一根棒棒糖吧 ୧(๑•̀⌄•́๑)૭



wechat pay



alipay

基于OCR的身份证信息提取
http://yuting0907.github.io/posts/ce9e260e.html
作者
Echo Yu
发布于
2025年5月22日
许可协议