如何使用Python和OpenCV从左到右排序轮廓,同时从上到下排序
我正在寻找一个带有数字和字符的图像轮廓,用于OCR。所以,我需要将轮廓从左到右排序,同时逐行排序,即从上到下。现在,轮廓不是这样排序的 例如,上面图像的轮廓是随机排序的 我需要的是排序为D,O,Y,O,U,K,N,O,W,S,O,M,E,O,N,E,R,(点),I(无点),C,H等。我尝试了两种方法,首先观察y坐标,然后使用一些键和x坐标。就像现在一样,我有下面的排序代码。它适用于前两行。然后在第三行,排序不知何故没有发生。主要问题似乎出现在字母中,如i、j、、(点),(逗号)等,其中(点)的y轴变化,尽管属于同一行。那么,有什么好的解决办法呢如何使用Python和OpenCV从左到右排序轮廓,同时从上到下排序,python,sorting,opencv,contour,Python,Sorting,Opencv,Contour,我正在寻找一个带有数字和字符的图像轮廓,用于OCR。所以,我需要将轮廓从左到右排序,同时逐行排序,即从上到下。现在,轮廓不是这样排序的 例如,上面图像的轮廓是随机排序的 我需要的是排序为D,O,Y,O,U,K,N,O,W,S,O,M,E,O,N,E,R,(点),I(无点),C,H等。我尝试了两种方法,首先观察y坐标,然后使用一些键和x坐标。就像现在一样,我有下面的排序代码。它适用于前两行。然后在第三行,排序不知何故没有发生。主要问题似乎出现在字母中,如i、j、、(点),(逗号)等,其中(点)的
for ctr in contours:
if cv2.contourArea(ctr) > maxArea * areaRatio:
rect.append(cv2.boundingRect(cv2.approxPolyDP(ctr,1,True)))
#rect contains the contours
for i in rect:
x = i[0]
y = i[1]
w = i[2]
h = i[3]
if(h>max_line_height):
max_line_height = h
mlh = max_line_height*2
max_line_width = raw_image.shape[1] #width of the input image
mlw = max_line_width
rect = np.asarray(rect)
s = rect.astype( np.uint32 ) #prevent overflows
order= mlw*(s[:,1]/mlh)+s[:,0]
sort_order= np.argsort( order )
rect = rect[ sort_order ]
我喜欢你用一次排序来解决这个问题。但正如您所说,每行中y的变化可能会破坏您的算法,另外,
max\u line\u height
可能需要根据不同的输入进行调整
因此,我会提出一个稍微不同的算法,但计算复杂度相当高。其思想是,如果您仅水平查看所有框,则第N+1
行中的所有框将永远不会与第1
行到N
行中的框相交,但它们在一行内彼此相交。因此,您可以先按它们的y
对所有框进行排序,逐个遍历并尝试找到“断点”(将它们分组为一行),然后在每行中,按它们的x
对它们进行排序
下面是一个不太像Python的解决方案:
# sort all rect by their y
rect.sort(key=lambda b: b[1])
# initially the line bottom is set to be the bottom of the first rect
line_bottom = rect[0][1]+rect[0][3]-1
line_begin_idx = 0
for i in xrange(len(rect)):
# when a new box's top is below current line's bottom
# it's a new line
if rect[i][1] > line_bottom:
# sort the previous line by their x
rect[line_begin_idx:i] = sorted(rect[line_begin_idx:i], key=lambda b: b[0])
line_begin_idx = i
# regardless if it's a new line or not
# always update the line bottom
line_bottom = max(rect[i][1]+rect[i][3]-1, line_bottom)
# sort the last line
rect[line_begin_idx:] = sorted(rect[line_begin_idx:], key=lambda b: b[0])
现在,
rect
应该按照您想要的方式进行排序。我使用了这个方法,它对我很有效。
在我的例子中,每行有5个等高线
def x_cord_contour(contours):
#Returns the X cordinate for the contour centroid
M = cv2.moments(contours)
return (int(M['m10']/M['m00']))
def y_cord_contour(contours):
#Returns the Y cordinate for the contour centroid
M = cv2.moments(contours)
return (int(M['m01']/M['m00']))
# Sort by top to bottom using our y_cord_contour function
contours_top_to_bottom = sorted(questionCnts, key = y_cord_contour, reverse = False)
for (q, i) in enumerate(np.arange(0, len(contours_top_to_bottom), 5)):
# sort the contours for the current question from left to right
# As in my example every row contain 5 coutours so now i sorted them in row wise
cnts = sorted(contours_top_to_bottom[i:i + 5], key = x_cord_contour, reverse = False)
# loop over the sorted contours
for (j, c) in enumerate(cnts):
# construct a mask that reveals only the current contour
#and do what ever you want to do
#....#
如果我错了,请纠正我请提供一个清晰的例子,说明第三行中什么不起作用。图像第三行的轮廓被排序为应力。ed,hav..i,n,g。等等这些点随机出现在其他字母的位置上,导致其他字母在正确的排序位置上散落。