我正在尝试用Python创建一个OCR系统 – 第一部分涉及从图像中提取所有字符。这部分工作得很好,所有字符都被分隔到各自的边界框中。
代码附在下面:
import numpy as npimport matplotlib.pyplot as pltimport matplotlib.patches as mpatchesfrom scipy.misc import imread,imresizefrom skimage.segmentation import clear_borderfrom skimage.morphology import labelfrom skimage.measure import regionpropsimage = imread('./ocr/testing/adobe.png',1)bw = image < 120cleared = bw.copy()clear_border(cleared)label_image = label(cleared,neighbors=8)borders = np.logical_xor(bw, cleared)label_image[borders] = -1print label_image.max()fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6))ax.imshow(bw, cmap='jet')for region in regionprops(label_image): if region.area > 20: minr, minc, maxr, maxc = region.bbox rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr, fill=False, edgecolor='red', linewidth=2) ax.add_patch(rect)plt.show()
然而,由于字母i和j上面有“点”,代码将这些点视为单独的边界框。我使用的是regionprops库。调整和标准化每个边界框的大小是否也是一个好主意?
我该如何修改代码来处理i和j?我理解的是,我需要合并附近的边界框?我尝试过但没有成功…谢谢。
回答:
是的,通常你希望标准化边界框的内容以适应你的字符分类器的输入尺寸(假设你正在处理具有显式分割的字符分类器,而不是隐式分割的序列分类器)。
对于合并同一字母的垂直隔离的连通组件,例如i和j,我会尝试使用各向异性的高斯滤波器(在x方向上的sigma值非常小,在y方向上较大)。确切的参数化将取决于你的输入数据,但通过实验应该很容易找到一个合适的值,使得所有字母都只产生一个连通组件。
另一种方法是分析与其他连通组件有水平重叠的连通组件,并合并那些重叠超过一定相对阈值的配对。
# Anisotropic Gaussianfrom scipy.ndimage.filters import gaussian_filterfiltered = gaussian_filter(f, (2,0))plt.imshow(filtered, cmap=plt.cm.gray)
# Now thresholdbin = filtered < 1plt.imshow(bin, cmap=plt.cm.gray)
很容易看出,现在每个字符都由一个连通组件表示。现在我们几乎只需要应用每个掩码并裁剪白色区域,就可以得到每个字符的边界框。在标准化它们的大小后,我们可以直接将它们输入到分类器中(不过要考虑到我们也失去了上升线/下降线信息以及宽高比,这些可能作为分类器的特征是有用的;因此,除了标准化的边界框内容外,还应该将它们明确地输入到分类器中)。