使用openCV和OCR从不规则形式中提取数据

时间:2016-07-26 18:23:08

标签: c# python c++ opencv

我试图从表单中提取信息(表单的扫描图像)并将该信息放入表格中。我已经使用pytesseract对图像进行了OCR取得了很好的成功,但输出的问题是Tesseract尝试逐行提取文本。

我的扫描表单如下所示: enter image description here

表格(A,B,C)的每个窗口应该是表格中的不同行。我试图使用Open Computer Vision(在python中)识别各个窗口1)识别单个数据单元(A,B,C),2)裁剪每个窗口,3)使用Tesseract OCR单个窗口的图像,将信息放在SQL表中需要的位置。

我的问题:如何识别每个表格输入窗口的边界,并将图像裁剪到该边界的范围(然后应用OCR)?此外,是否可以使用角点检测来识别各个数据单元?

我主要在OpenCV上使用python,并且熟悉文档以将C#/ ++ OpenCV解决方案应用于python脚本,所以我将非常感谢您提供的任何信息/替代解决方案。

2 个答案:

答案 0 :(得分:5)

可以单独使用轮廓和简单轮廓属性将它们分开。

注意:这些程序仅适用于此特定表单。它不是各种不规则形式的通用解决方案。但是,您可以实施或调整某些方法,以使其适用于您的表单

首先阅读图片

image=cv2.imread("TDtma.png")

将其转换为灰度

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

使用Canny Edge滤镜获取边缘 - 通过随机试验选择值600,1000。我选择了这个值,因为它正确地删除了背景神器。您可能需要更改并为此选择正确的值,具体取决于您要输入的图像。

edges = cv2.Canny(gray,600,1000) Canny edge detection

使用模糊滤镜移除现实世界中存在的微小瑕疵(如手写等)

edges = cv2.GaussianBlur(edges,(5,5),0) # To remove small artifacting if any

接下来我们找到外部轮廓,因为3个矩形(部分)明显分开,我们需要做的就是找到所有外部轮廓。请注意,此代码可能与OpenCV 2.4.x不同。

(_,contours,_) = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

由于某些原因,从下到上检测轮廓。所以我们有一个字符C递减到A只是为了标记我们感兴趣的区域。

FormPart = ord('C')

遍历每个轮廓,然后裁剪感兴趣的区域。

我们检查每个轮廓是否具有正确的纵横比和面积,这些值(纵横比:2,面积:1000)也是通过实验获得的,并且可能需要根据实际输入图像进行更改。 理想情况下,在我们的情况下,矩形应该具有宽高比> 2(矩形的一侧总是大于另一侧,该图像中的矩形具有> 2的比率)。我们检查区域是否> 1000,以避免由于小的伪影而检测到的任何类型的轮廓。同样,这些值可能需要相应地改变,以便适当地处理真实世界的图像。

即使不检查轮廓区域和纵横比,也会正确处理此给定图像,但由于小斑点可能会出现真实图像问题,因此为了避免它们,区域/纵横比检查正在进行中

for contour in contours: x,y,w,h = cv2.boundingRect(contour) aspect_ratio = w / float(h) area = cv2.contourArea(contour) if aspect_ratio<2 or area >1000: # Just to check whether we have the right contour, if not we go to the next contour continue crop_img = image[y:y+h,x:x+w] #This is our region of interest cv2.imshow("Split Section "+chr(FormPart), crop_img) cv2.waitKey(0) FormPart=FormPart-1 if chr(FormPart) < ord('A'): # If there are more than 3 sections break

最后,我们在这里有一个完整的程序,您可以复制并粘贴并在您的计算机上运行。确保你有Python&gt; 2.7.x和OpenCV 3.可能需要更改某些行以便使用OpenCV 2.4 还要确保图像名为“TDtma.png”,并且与Python程序位于同一目录中

import cv2
image=cv2.imread("TDtma.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,600,1000) # To remove the irrelevant edges and show the relevant ones
cv2.imshow("Canny edge detection", edges)
cv2.waitKey(0)


edges = cv2.GaussianBlur(edges,(5,5),0) # To remove small artifacting if any

(_,contours,_) = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # Detecting external contours

#If you are on opencv 2.4x use this
#(contours,_)= cv2.findContours(edgescopy, cv2.RETR_EXTERNAL,  cv2.CHAIN_APPROX_SIMPLE)
FormPart = ord('C')# Contour goes from bottom to top in this example
for contour in contours:
    x,y,w,h = cv2.boundingRect(contour)
    aspect_ratio = w / float(h)
    area = cv2.contourArea(contour)
    if aspect_ratio<2 or area <1000:  #Go to next contour if this contour doesnt meet our specifications
        continue
    crop_img = image[y:y+h,x:x+w] #This is our region of interest
    cv2.imshow("Split Section "+chr(FormPart), crop_img)
    cv2.waitKey(0)
    FormPart=FormPart-1
    if chr(FormPart) < ord('A'): # If there are more than 3 sections
        break

最后你应该有这样的东西 Final result

也可以在文本字段中分离这些单独的数据单元格。虽然它有点复杂,但可能无法正确处理真实世界的图像。如果你想我可以尝试。如果需要,请发表评论。

希望我能够提供帮助

答案 1 :(得分:2)

在这种情况下,你应该做的是看看OpenCV findContours。确保使用RETR_TREE检索方法来获取轮廓的层次结构。

您的窗户应该是图片中最高级别的轮廓。请参阅我的回答here,了解如何导航OpenCV返回的层次结构。