Python Opencv 图片识别表格:边框线检测

图片识别表格的一个重要步骤是检测出图片中表格的边框线。

opencv中检测矩形框的函数 python opencv 边框识别_python


边框线检测最大的挑战是笔画中出现的横线和竖线。你可能认为可以通过线条的长短来区分,但如果是一张密集的表格,某个边框线只出现在一个单元格里,它也会很短。因此这种思路也会有兼容性问题。

网上有很多关于线段检测的算法,但是都只是在某种特定情况下是可行的,当我们要识别各种图片中的各种表格时,不得不考虑一种更健壮更全面的算法。

整体思路如下:

  • 通过image_binary变为二值图像 确保图像为白底黑字,因为稍后的操作都是膨胀白色
  • 通过dilate膨胀白色横块抹去文字和竖线。因为文字的笔画之间是有白色间隙的,通过白色横块膨胀,文字会被大部分抹去,除了极少的横线笔画。膨胀结果取反变成黑底白线得到A
  • 通过dilate膨胀白色竖块抹去文字和横线。因为文字的笔画之间是有白色间隙的,通过白色竖块膨胀,文字会被大部分抹去,除了极少的竖线笔画。膨胀结果取反变成黑底白线得到B
  • AB结果通过bitwise_or合并得到边框检测结果

采用dilate算法时最重要的是kernel的设计,kernel最重要的是size,网上看到的算法大部分是按照图片宽高进行一个比列的缩放得到size,实际效果并不好。我们这个算法采用了图片宽高的平方根进行一定的调整后形成size,实测效果非常好,很好的解决了图片分辨率和线条之间的关系。

opencv中检测矩形框的函数 python opencv 边框识别_算法_02


完整代码如下:

#转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

#转为二值图
ret, binary = cv2.threshold(gray, black_thr, 255, cv2.THRESH_BINARY)

# 膨胀算法的色块大小
h, w = binary.shape
hors_k = int(math.sqrt(w)*1.2)
vert_k = int(math.sqrt(h)*1.2)

# 白底黑字,膨胀白色横向色块,抹去文字和竖线,保留横线
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (hors_k,1))
hors = ~cv2.dilate(binary, kernel, iterations = 1) # 迭代两次,尽量抹去文本横线,变反为黑底白线

# 白底黑字,膨胀白色竖向色块,抹去文字和横线,保留竖线
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,vert_k))
verts = ~cv2.dilate(binary, kernel, iterations = 1) # 迭代两次,尽量抹去文本竖线,变反为黑底白线

# 横线竖线检测结果合并
borders = cv2.bitwise_or(hors,verts)

需要注意的是都是对dilate的结果取反得到黑底白线,便于后面通过bitwise_or叠加得到borders

实际效果如下:

黑白二值:

opencv中检测矩形框的函数 python opencv 边框识别_ocr_03


横线检测:

opencv中检测矩形框的函数 python opencv 边框识别_图像识别_04

竖线检测:

opencv中检测矩形框的函数 python opencv 边框识别_算法_05

边框合并

opencv中检测矩形框的函数 python opencv 边框识别_图像识别_06

可以看到算法结束后,仍然存在一些干扰点,因此还需要进一步的算法进行过滤,将在后续文章中讲解。