【问题标题】:Detecting Interword Space in OCR using Python and OpenCV使用 Python 和 OpenCV 检测 OCR 中的字间空间
【发布时间】:2018-05-17 13:17:16
【问题描述】:

我是 Python 和 OpenCV 的新手。我目前正在使用 Python 和 OpenCV 不使用 Tesseract 进行 OCR。到目前为止,我已经成功地检测到文本(字符和数字),但是在检测单词之间的空格时遇到了问题。 例如- 如果图像显示“Hello John”,那么它会检测到 hello john 但无法检测到它们之间的空间,所以我的输出是“HelloJohn”,它们之间没有任何空间。我提取轮廓的代码如下(我已经导入了所有需要的模块,这个是提取轮廓的主要模块):

 imgGray = cv2.cvtColor(imgTrainingNumbers, cv2.COLOR_BGR2GRAY)
 imgBlurred = cv2.GaussianBlur(imgGray, (5,5), 0)                        


 imgThresh = cv2.adaptiveThreshold(imgBlurred,                           
                                  255,                                  
                                  cv2.ADAPTIVE_THRESH_GAUSSIAN_C,       
                                  cv2.THRESH_BINARY_INV,                
                                  11,                                   
                                  2)                                    

 cv2.imshow("imgThresh", imgThresh)      

 imgThreshCopy = imgThresh.copy()        

 imgContours, npaContours, npaHierarchy = cv2.findContours(imgThreshCopy,        
                                             cv2.RETR_EXTERNAL,                 
                                             cv2.CHAIN_APPROX_SIMPLE)           

在此之后,我将提取的轮廓分类为数字和字符。 请帮我检测它们之间的空间。 提前感谢您,您的回复将非常有帮助。

【问题讨论】:

  • 这样你就有了带有字母的二进制图像。一种方法是使用dilation 增加字母,直到附近的字符合并,但单独的单词不会。然后,每个单词都有单独的 blob。这些斑点的轮廓每个都是单个单词的掩码,您可以使用每个斑点单独掩盖原始图像,只需对单独的单词进行 OCR。

标签: python-2.7 opencv


【解决方案1】:

由于您没有提供任何示例图像,我只是生成了一个简单的图像进行测试:

h, w = 100, 600
img = np.zeros((h, w), dtype=np.uint8)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, 'OCR with OpenCV', (30, h-30), font, 2, 255, 2, cv2.LINE_AA)

正如我在 cmets 中提到的,如果您只是 dilate 图像,那么白色区域将会扩大。如果您使用足够大的内核执行此操作,以使附近的字母合并,但又足够小以至于单独的单词不会合并,那么您将能够提取每个单词的轮廓,并使用它一次掩盖一个单词以用于 OCR 目的。

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15, 15))
dilated = cv2.dilate(img, kernel)

要单独获取每个单词的掩码,只需找到这些较大斑点的轮廓即可。您也可以对轮廓进行排序;垂直,水平或两者兼而有之,以便您以正确的顺序获得单词。在这里,因为我只有一行,所以我将按x 方向排序:

contours = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[1]
contours = sorted(contours, key=lambda c: min(min(c[:, :, 0])))

for i in range(len(contours)):

    mask = np.zeros((h, w), dtype=np.uint8)

    # i is the contour to draw, -1 means fill the contours
    mask = cv2.drawContours(mask, contours, i, 255, -1)
    masked_img = cv2.bitwise_and(img, img, mask=mask)

    cv2.imshow('Masked single word', masked_img)
    cv2.waitKey()

    # do your OCR here on the masked image

【讨论】:

  • 非常感谢,您的代码有效...您减轻了我的负担,再次感谢您:)
  • 你能帮我扩展代码吗,如果文本是多行而不是一行,例如只喜欢这个评论。
  • 我建议采取与我上面所做的类似的方法。尝试使用长水平线内核进行扩张:kernel = np.ones((1, 100), dtype=np.uint8) 并查看您得到的响应。这将为您提供每行的掩码。只需屏蔽每一行,然后对该行重复上述操作。
  • 再次感谢您....现在我的项目已经完成提交..感谢您:)
  • 先生,我们正在尝试使用相同的工具扩展我们的货币检测项目。是否可以使用相同的工具进行检测。我试图通过使用内核侵蚀货币来提取货币的边缘,但由于背景原因,我无法检测到与数字对应的轮廓,例如 100。所以无论如何请你帮我?
猜你喜欢
  • 1970-01-01
  • 2018-02-10
  • 1970-01-01
  • 1970-01-01
  • 2013-02-05
  • 2010-10-29
  • 1970-01-01
  • 1970-01-01
  • 2011-12-19
相关资源
最近更新 更多