我想使用轮廓检测​​对从图像中提取的单词进行排序

I want to sort the words extracted from image in order of their occurence using contours detection

我正在制作 OCR,我正在使用轮廓检测​​,我已经提取了单词并绘制了边界框,但问题是当我裁剪单个单词时,它们没有按排序顺序排列。我已经尝试过此 link 中提到的排序方法来对轮廓进行排序,但它们在对象上效果最好,但在我的情况下,我想使顺序准确。有时排序不是最好的解决方案,它会改变单词的模式,因为不同的单词在同一行中具有不同大小的边界框,并且 'x' 和 'y' 的值会随之变化。现在在同一行中,具有大边界框的单词被视为一个类别,而小边界框被视为另一类别,并且它们在同一行中进行排序 fashion.This 是要排序的代码。

    sorted_ctrs=sorted(ctrs, key=lambda ctr: cv2.boundingRect(ctr)[0] + cv2.boundingRect(ctr)[1] * 
    im.shape[1] )

image of extracted bounded boxes
this is what I get after cropping from sorted contours

有没有其他方法可以把我的话整理得有意义一些?

您应该先将不同的行分开。完成后,您可以简单地从左到右处理轮廓(从 x = 0 到 x = width 排序)

首先在黑色背景上绘制找到的轮廓。接下来,对行求和。没有 words/contours 的行的总和将为 0。文本行之间通常有一些 space,其总和 = 0。您可以使用它来查找每行的最小和最大高度值文本。

要查找单词的顺序,首先查找第一行 y 范围内的轮廓,然后查找最低的 x。

输入:

代码:

import cv2
import numpy as np
# load image and get dimensions
img = cv2.imread('xmple2.png',0)
h,w = img.shape[:2]
# sum all rows
sumOfRows = np.sum(img, axis=1)

# loop the summed values
startindex = 0
lines = []
compVal = True
for i, val in enumerate(sumOfRows):
    # logical test to detect change between 0 and > 0
    testVal = (val > 0)
    if testVal == compVal:
            # when the value changed to a 0, the previous rows
            # contained contours, so add start/end index to list
            if val == 0:
                lines.append((startindex,i))
            # update startindex, invert logical test
                startindex = i+1
            compVal = not compVal

您使用lines列表进一步处理等高线。以下代码生成一个列表,其中的轮廓根据位置排序,您可以通过图像上的列表索引看到:

# create empty list
lineContours = []
# find contours (you already have this)
x, contours, hier = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
# loop contours, find the boundingrect,
# compare to line-values
# store line number,  x value and contour index in list
for j,cnt in enumerate(contours):
    (x,y,w,h) = cv2.boundingRect(cnt)
    for i,line in enumerate(lines):
        if y >= line[0] and y <= line[1]:
            lineContours.append([line[0],x,j])
            break

# sort list on line number,  x value and contour index
contours_sorted = sorted(lineContours)

# write list index on image
for i, cnt in enumerate(contours_sorted):
    line, xpos, cnt_index = cnt
    cv2.putText(img,str(i),(xpos,line+50),cv2.FONT_HERSHEY_SIMPLEX,1,(127),2,cv2.LINE_AA)

# show image
cv2.imshow('Img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

您可以改为打印轮廓索引:

# write contour index on image
for line, xpos, cnt_index in (contours_sorted):
    cv2.putText(img,str(cnt_index),(xpos,line+50),cv2.FONT_HERSHEY_SIMPLEX,1,(127),2,cv2.LINE_AA)

您还可以为单独的行创建图像:

# for each line found, create and display a subimage
for y1,y2 in lines:
    line = img[y1:y2,0:w]
    cv2.imshow('Img',line)
    cv2.waitKey(0)

cv2.destroyAllWindows()