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

如何基于印度车牌规则与OCR检测框坐标对识别字符进行正确排序

印度车牌OCR识别乱序问题解决方案

一、检测框参数提取与坐标排序

1. 四点坐标转(x,y,w,h)参数

keras-ocr返回的每个文本块对应4个顶点的多边形坐标,按如下方式计算外接矩形参数:

import numpy as np

def get_box_xywh(box):
    # box为keras-ocr返回的4*2坐标数组
    x_coords = box[:, 0]
    y_coords = box[:, 1]
    x = np.min(x_coords)
    y = np.min(y_coords)
    w = np.max(x_coords) - x
    h = np.max(y_coords) - y
    # 额外返回y轴中心坐标用于分行判断
    y_center = np.mean(y_coords)
    return (x, y, w, h, y_center)

2. 基于坐标的排序逻辑

印度车牌多为1行或2行布局,按以下规则排序即可得到基础的正确顺序:

  • 先按文本块的y_center值分组:两个文本块y_center差值小于任意一个块高度h的1/2时,判定为同一行
  • 行与行之间按y_center从小到大排序(从上到下读取)
  • 同一行内的文本块按x坐标从小到大排序(从左到右读取)
    排序代码示例:
def sort_by_coordinate(ocr_results):
    # ocr_results为keras-ocr返回的原生列表,元素格式为(识别文本, 框坐标)
    processed = []
    for text, box in ocr_results:
        x, y, w, h, y_center = get_box_xywh(box)
        processed.append((text, x, y, w, h, y_center))
    # 先按y轴中心预排序再分行
    processed_sorted_by_y = sorted(processed, key=lambda x: x[-1])
    lines = []
    current_line = [processed_sorted_by_y[0]]
    for item in processed_sorted_by_y[1:]:
        last_item = current_line[-1]
        if abs(item[-1] - last_item[-1]) < min(item[3], last_item[3]) * 0.5:
            current_line.append(item)
        else:
            lines.append(current_line)
            current_line = [item]
    lines.append(current_line)
    # 每行内按x坐标排序后拼接结果
    sorted_text = []
    for line in lines:
        line_sorted = sorted(line, key=lambda x: x[1])
        sorted_text.extend([item[0] for item in line_sorted])
    return ' '.join(sorted_text).upper()

二、结合印度车牌规则的结果优化

你适配的德里(DL)、哈里亚纳邦(HR)、北方邦(UP)车牌遵循印度标准格式:[两位邦代码] [1~2位地区代码] [1~2位字母序列] [4位数字],按以下步骤做二次校验修正,可解决坐标排序的残留误差:

  1. 预处理:将所有识别结果转大写,提前替换易混淆字符(如数字0转字母O、数字1转字母I等,可根据自身识别准确率调整规则),同时将地区代码字典统一为字符串格式,避免匹配失败
  2. 匹配邦代码:从排序后的字符串中提取所有连续两位的字母,匹配目标邦列表['DL','HR','UP'],确定邦代码位置
  3. 匹配地区代码:取邦代码后紧邻的1~2位数字,匹配对应邦的地区代码列表
  4. 格式重排:将识别出的内容按邦代码-地区代码-字母序列-4位数字的固定顺序重排,修正坐标排序的误差
    优化代码示例:
# 预处理地区代码字典,统一为2位字符串格式
district_codes['HR'] = [str(i).zfill(2) for i in district_codes['HR']]
district_codes['DL'] = [i.zfill(2) for i in district_codes['DL']]
# UP的地区代码可按同样逻辑补充
target_states = {'DL','HR','UP'}

def optimize_by_plate_rule(raw_text):
    # 去掉空格方便匹配
    text_no_space = raw_text.replace(' ', '')
    # 匹配邦代码
    state_code = None
    state_pos = -1
    for i in range(len(text_no_space)-1):
        candidate = text_no_space[i:i+2]
        if candidate in target_states:
            state_code = candidate
            state_pos = i
            break
    if not state_code:
        # 未匹配到目标邦代码时返回坐标排序的原始结果
        return raw_text
    # 匹配地区代码
    district_code = None
    remaining = text_no_space[state_pos+2:]
    # 优先匹配2位地区代码,再匹配1位
    for l in [2,1]:
        if len(remaining) >= l:
            cand_dist = remaining[:l]
            if cand_dist in district_codes.get(state_code, []):
                district_code = cand_dist
                break
    # 拆分剩余的字母序列和4位数字
    rest = remaining[len(district_code):] if district_code else remaining
    digit_part = ''.join([c for c in rest if c.isdigit()])[-4:]
    alpha_part = ''.join([c for c in rest if c.isalpha()])[:2]
    # 拼接为标准格式
    return f"{state_code} {district_code} {alpha_part} {digit_part}"

补充优化建议

  • 针对OCR识别的字符混淆问题,可在邦代码、地区代码匹配环节增加容错规则,比如单字符差异的模糊匹配
  • 如果车牌存在形变、倾斜的情况,可先对检测框做透视校正后再排序,准确率会更高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 16:51:01