我想使用轮廓检测对从图像中提取的单词进行排序
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()
我正在制作 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()