可以单独使用轮廓和简单的轮廓属性将它们按部分分开。
注意:这些程序仅适用于这种特殊形式。它不是各种不规则形式的通用解决方案。但是,您可以实现或调整某些方法以使其适用于您的表单
先读取图片
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 和 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
最后你应该有这样的东西
也可以在文本字段中分隔这些单独的数据单元格。虽然它有点复杂,但可能不适用于真实世界的图像。如果你愿意我可以试试。有需要可以留言。
希望我能帮上忙