【问题标题】:Rearranging License Plate characters based on country根据国家/地区重新排列车牌字符
【发布时间】:2021-08-13 05:00:46
【问题描述】:

我正在做一个车牌/车牌识别项目,我正在完成阶段但有一个小问题,我已经成功识别了字符,请考虑以下示例:

这是一张输入图片,我得到的预测是2791 2g rj14

尽你所能,ocr 做得很好,但安排被破坏了(破坏了整个目的)。 有时它会以正确的顺序输出,但有时却不会,所以当它没有以正确的顺序输出时,我正在尝试开发一种算法,它将预测的num_plate 字符串作为输入并根据我的国家(印度)重新排列。

下面是一些图片,告诉我们印度号码/车牌的格式。

另外,我收集了所有州,但现在,我只想为 3 个州做:德里 (DL)、哈里亚纳邦 (HR)、北方邦 (UP)。更多信息:https://en.wikipedia.org/wiki/List_of_Regional_Transport_Office_districts_in_India

total_states_list = [
    'AN','AP','AR','AS','BR','CG','CH','DD','DL','DN','GA','GJ','HR','HP','JH','JK','KA','KL',
    'LD','MH','ML','MN','MP','MZ','NL','OD','PB','PY','RJ','SK','TN','TR','TS','UK','UP','WB'
]

district_codes = {
    'DL': ['1','2','3','4','5','6','7','8','9','10','11','12','13'],
    'HR': [01,02,03,04,05,06,07,08,09,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
            40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,
            71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99
    ]
}

所以,我一直在尝试,但无法提出一种算法,如果不是,则将序列重新排列为所需的序列。任何帮助将不胜感激。

关于 OCR 的详细信息

使用keras-ocr,我得到以下输入图像的输出:

[
  ('hrlz',  array([[ 68.343796,  42.088367],
                   [196.68803 ,  26.907867],
                   [203.00832 ,  80.343094],
                   [ 74.66408 ,  95.5236  ]], dtype=float32)), 
  ('c1044', array([[ 50.215836, 113.09602 ],
                   [217.72466 ,  92.58473 ],
                   [224.3968  , 147.07387 ],
                   [ 56.887985, 167.58516 ]], dtype=float32))
]

来源:https://keras-ocr.readthedocs.io/en/latest/examples/using_pretrained_models.html

keras_ocr.tools.drawAnnotations 内,我认为它们是预测框。所以我找到了这个文件,找到了drawAnnotations函数的实现,这里是:

def drawAnnotations(image, predictions, ax=None):
  if ax is None:
        _, ax = plt.subplots()
    ax.imshow(drawBoxes(image=image, boxes=predictions, boxes_format='predictions'))
    predictions = sorted(predictions, key=lambda p: p[1][:, 1].min())
    left = []
    right = []
    for word, box in predictions:
        if box[:, 0].min() < image.shape[1] / 2:
            left.append((word, box))
        else:
            right.append((word, box))
    ax.set_yticks([])
    ax.set_xticks([])
    for side, group in zip(['left', 'right'], [left, right]):
        for index, (text, box) in enumerate(group):
            y = 1 - (index / len(group))
            xy = box[0] / np.array([image.shape[1], image.shape[0]])
            xy[1] = 1 - xy[1]
            ax.annotate(s=text,
                        xy=xy,
                        xytext=(-0.05 if side == 'left' else 1.05, y),
                        xycoords='axes fraction',
                        arrowprops={
                            'arrowstyle': '->',
                            'color': 'r'
                        },
                        color='r',
                        fontsize=14,
                        horizontalalignment='right' if side == 'left' else 'left')
    return ax

我应该如何获取 (x,y,w,h),然后根据 number_plate bbox 的 y/x 以某种方式排序/打印?

编辑 - 2

我设法得到了字符的边界框,如下图所示:

使用函数cv2.polylines(box),其中box 与我之前粘贴输出的坐标相同。现在我如何按照 cmets 中的人建议的顺序打印它们,从左到右...使用 y/x。

【问题讨论】:

  • 这些序列如何重新排列有什么规律吗?
  • @ScottHunter 是的,看我附上了一张图片,其中州代码首先出现(2 位数字),然后是地区代码 district_codes(有时是 1 或 2 位数字),然后是唯一的组合。 ..
  • 你获取块的格式是什么?它是空格分隔的单个字符串吗?字符串列表?
  • @trincot 它是一个字符串,例如:detected_num_plate = '27912grj14'
  • 好的,但是你无法知道真正的车牌是否可能是rj1214279g。还是你有更多的规则?

标签: python python-3.x algorithm


【解决方案1】:

如果可以得到每个识别出的文本框的坐标,那么:

  • 旋转坐标,使框与 X 轴平行
  • 缩放 Y 坐标,使其可以四舍五入为整数,这样并排的框将获得相同的整数 Y 坐标(如行号)
  • 先按 Y,再按 X 坐标对数据进行排序
  • 按该顺序提取文本

以下是此类序列的示例:

data = [
  ('hrlz', [[ 68.343796,  42.088367],
            [196.68803 ,  26.907867],
            [203.00832 ,  80.343094],
            [ 74.66408 ,  95.5236  ]]), 
  ('c1044',[[ 50.215836, 113.09602 ],
            [217.72466 ,  92.58473 ],
            [224.3968  , 147.07387 ],
            [ 56.887985, 167.58516 ]])
]

# rotate data to align with X-axis
a, b = data[0][1][:2]
dist = ((b[1] - a[1]) ** 2 + (b[0] - a[0]) ** 2) ** 0.5
sin = (b[1] - a[1]) / dist
cos = (b[0] - a[0]) / dist
data = [
    (text, [(x * cos + y * sin, y * cos - x * sin) for x, y in box]) for text, box in data
]

# scale Y coordinate to integers
a, b = data[0][1][1:3]
height = b[1] - a[1]
data = [
    (round(box[0][1] / height), box[0][0], text) 
        for text, box in data
]

# sort by Y, then X
data.sort()

# Get text in the right order
print("".join(text for _, _, text in data))

这假设框的点按以下顺时针顺序给出:

top-left, top-right, bottom-right, bottom-left

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-31
    • 2020-02-27
    • 2019-04-15
    • 2020-11-28
    • 2013-08-18
    • 2018-07-06
    • 1970-01-01
    相关资源
    最近更新 更多