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

crl*_*rld 5 c# c++ python opencv

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

我扫描的表格如下所示: 在此处输入图片说明

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

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

我主要在OpenCV中使用python,并且对将C#/ ++ OpenCV解决方案应用于python脚本的文档非常熟悉,因此,我希望您能提供任何信息/替代解决方案。

Tit*_*boa 5

可以仅使用轮廓和简单的轮廓属性将它们按节分开。

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

首先阅读图片

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

将其转换为灰度

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

使用Canny Edge滤镜获取边缘-通过随机实验选择了值600,1000。我选择此值是因为它可以正确删除背景伪像。您可能需要根据要输入的图像来更改并选择正确的值。

edges = cv2.Canny(gray,600,1000) 卡尼边缘检测

使用模糊滤镜去除现实图像中会出现的细微伪影(例如笔迹等)

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> 2.7.x和OpenCV3。可能需要更改某些行才能与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
Run Code Online (Sandbox Code Playgroud)

最后你应该有这样的东西 最后结果

也可以在文本字段中分隔这些单独的数据单元。不过,这有点复杂,可能无法正确处理现实世界的图像。如果您愿意,我可以尝试。如有需要,请发表评论。

希望我能提供帮助