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

TensorFlow CNN OCR识别波斯车牌字符错误的排查与优化咨询

波斯车牌OCR识别错误排查与优化方案

我基于FastAPI构建波斯车牌识别Web API,采用YOLOv8检测车牌边界框(检测结果正确),但自定义TensorFlow CNN模型的OCR步骤输出错误或随机字符(如输出“1سیب32لف”而非“56ب123 24”)。

当前实现流程

  • 车牌检测:使用ultralytics的YOLOv8检测车牌区域,可视化验证结果正确。
  • 预处理:裁剪车牌区域,应用Otsu阈值处理,通过霍夫直线校正旋转,基于固定宽度比例分割字符。
  • OCR模型:训练了两个CNN模型(plate_trainer.py和hand_written_trainer.py),分别识别波斯数字(0-9)与字母(如‘ب’‘س’),当前使用simple_ocr_plates_model1.keras。
  • 训练细节:基于约10000张标注字符图像(含波斯数字与字母)训练,加入旋转、缩放等数据增强,一个模型针对印刷车牌,另一个针对手写风格字符。

核心代码片段

import cv2 as cv
import numpy as np
import tensorflow as tf

# Load CNN model
ocr_model = tf.keras.models.load_model('models/simple_ocr_plates_model1.keras')
class_names = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'ﺎ', 'ﺐ', ...]  # 80+ Persian characters

def segment_characters(cropped_img: np.ndarray, output_dir: str) -> list:
    h, w = cropped_img.shape
    chopfactors = [(40, 120), (100, 200), ...]  # Scaled for plate width
    plate_letters = []
    for i, (w1, w2) in enumerate(chopfactors):
        w1, w2 = int(w1 * w / 600), int(w2 * w / 600)
        if w1 >= w2 or w1 >= w:
            continue
        letter_patch = cropped_img[:, w1:w2]
        if letter_patch.shape[1] == 0:
            continue
        letter_patch_resized = cv.resize(letter_patch, (30, 30))
        plate_letters.append(letter_patch_resized)
    return plate_letters

def recognize_characters(plate_letters: list) -> list:
    plate_letters = np.array(plate_letters)
    plate_letters = np.expand_dims(plate_letters, axis=-1) / 255.0
    predictions = ocr_model.predict(plate_letters, verbose=0)
    return [class_names[k] for k in np.argmax(predictions, axis=1)]

# Example usage
img = cv.imread("plate.jpg", cv.IMREAD_GRAYSCALE)
# ... (cropping and rotation steps)
cropped_img = adjust_cropping(rotated_img, output_dir)
plate_letters = segment_characters(cropped_img, output_dir)
plate_text = recognize_characters(plate_letters)
print(plate_text)  # Outputs: ['1', '2', '3'] instead of ['ب', '۱', '۲']

已尝试的排查动作

  • 可视化分割后的字符补丁,确认字符分割正确。
  • 测试两个CNN模型,印刷车牌模型表现略好,但均难以准确识别波斯字母。
  • 增加数据量重新训练,验证准确率达约95%,但实际场景仍识别错误。
  • 检查预处理步骤,阈值与缩放无明显问题,但怀疑归一化或分割存在隐患。

输出对比

预期:45 ب 123 11
实际:123ثثث۳ل


问题分析与优化方案

可能的原因

  1. 字符分割隐患:固定宽度比例分割无法适配不同车牌的字符间距、字体大小差异,波斯字符本身宽度有差异(如“ب”和“س”),固定比例易导致字符截断或包含多余背景,干扰模型识别。
  2. 训练数据与实际场景偏差:训练数据虽有10000张,但可能和实际场景的车牌在字体、光照、磨损、拍摄角度上差异极大——比如训练数据是清晰标准字体,实际场景存在模糊、阴影、污渍,导致验证准确率高但泛化能力差。
  3. 模型适配性不足:基础CNN结构可能不足以捕捉波斯字符的细微特征(如“ب”和“پ”的差异);分开训练数字、字母模型,但推理时未区分输入类型,易造成混淆。
  4. 预处理细节遗漏:
    • 未针对性去除车牌边框、反光等噪声;
    • 字符缩放时的插值方式导致边缘细节丢失;
    • 未统一字符对比度、亮度,或存在方向/镜像错误。

优化措施

  1. 改进字符分割

    • 替换固定比例分割为轮廓检测分割:对裁剪后的车牌做轮廓提取,过滤小噪声轮廓,按波斯文从右到左的顺序排序轮廓,提取外接矩形作为字符区域;
    • 加入宽高比过滤:根据波斯车牌字符的标准宽高比,过滤不符合的轮廓,减少无效分割。
  2. 优化训练数据

    • 补充实际场景样本:收集模糊、有污渍、不同光照下的车牌,裁剪字符标注后加入训练集;
    • 增强针对性数据增强:加入轻微模糊、阴影、噪声模拟,以及±5度的微小旋转,提升模型泛化能力;
    • 校验标注准确性:重点核查相似波斯字符(如“ث”和“ت”)的标注是否正确。
  3. 模型优化

    • 更换为CRNN模型:循环卷积神经网络可处理序列字符,减少分割错误的影响,同时捕捉字符上下文信息;
    • 合并数字与字母识别模型:使用单一多分类模型同时识别两类字符,避免模型切换的混淆;
    • 加入注意力机制:让模型聚焦于字符的关键特征区域,提升相似字符的区分度。
  4. 完善预处理流程

    • 噪声去除:阈值处理前加入高斯模糊或中值滤波;
    • 优化缩放插值:使用cv.INTER_CUBIC或cv.INTER_LANCZOS4插值,保留字符边缘细节;
    • 对比度增强:采用CLAHE(限制对比度自适应直方图均衡化)提升字符与背景的对比度;
    • 方向校正:通过计算字符最小外接矩形角度,确保字符方向正确,无镜像或旋转错误。
  5. 推理阶段后处理

    • 格式校验:根据波斯车牌的格式规则(如“数字+字母+数字+数字”结构),过滤连续相同字母等不符合规则的结果;
    • 置信度过滤:只保留预测置信度高于0.8的结果,低置信度字符重新分割或标记为未知。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 09:22:15