字检测算法实现
适用性
- 横板文本检测
- 竖版局检测
- 多列布局检测
- 类表格布局检测
1. 通用文字检测方法
对于竖版,先垂直检测识别出文字列,再逐列水平检测,识别出单个文字。再增加预处理、文字大小计算、参数调节等步骤来调节效果。
核心代码如下:
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, params['vertical_kernel'])
dilated_col = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, vertical_kernel, iterations=3)
# 查找文字列轮廓
text_contours, _ = cv2.findContours(dilated_col, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for i, cnt in enumerate(text_contours):
x, y, w_cnt, h_cnt = cv2.boundingRect(cnt)
roi = thresh[y:y+h_cnt, x:x+w_cnt]
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, params['horizontal_kernel'])
clean_roi = cv2.morphologyEx(roi, cv2.MORPH_CLOSE, horizontal_kernel)
char_contours, _ = cv2.findContours(clean_roi, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 按垂直位置排序字符
sorted_chars = sorted(char_contours, key=lambda c: cv2.boundingRect(c)[1])
for char in sorted_chars:
# 最终文字
cx, cy, cw, ch = cv2.boundingRect(char)
opencv 文字检测需要的函数手册与函数执行后的效果图见:https://download.youkuaiyun.com/download/qq_38418314/90927136
1. 类表格布局优化方法
如图,由于图像四周有封闭的边框,针对这种格式,正常的检测算法会把矩形框内部所有当作一个整体,导致检测失败。
1.1 解决思路:
既然由于最外层边框导致,那就想办法去除边框。由于这个布局和表格相似,想到是否可以用表格检测的算法来进行矫正。恰好opencv中提供了表格线去除的方法。
1.2 核心函数
table_mask = cv2.bitwise_or(horizontal, vertical)
作用:合并水平和垂直表格线的掩膜,生成一个完整的表格结构掩膜。通过逻辑或操作(OR),将两者的白色像素(值为255的区域)合并,得到完整的表格线区域。
参数说明:
horizontal:水平线掩膜(二值图像)。
vertical:垂直线掩膜(二值图像)。
table_mask:输出图像,包含所有水平和垂直表格线。
效果:合并后的 table_mask 会包含所有检测到的表格线,无论水平还是垂直方向。
thresh = cv2.subtract(thresh, table_mask)
作用:从原始二值图像中减去表格线掩膜,目的是去除表格线,保留其他内容。subtract() 会逐像素执行减法操作,如果表格线在 thresh 中是白色(255),则减去后这些区域会变为黑色(0),从而消除表格线。
参数说明
thresh:原始二值图像(可能包含文字和表格线)。
table_mask:表格线掩膜。
输出 thresh:去除表格线后的图像。
效果:
1.3 完整代码:
image = cv2.imread(img_path)
# 转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, params['gaussian_kernel'], 0)
# 二值化(黑底白字)
thresh = cv2.adaptiveThreshold(blurred, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV, params['block_size'], 4)
# 检测水平线
h_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (30,1))
horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, h_kernel, iterations=2)
# 检测垂直线
v_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,30))
vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, v_kernel, iterations=2)
# 合并并去除表格线
table_mask = cv2.bitwise_or(horizontal, vertical)
thresh = cv2.subtract(thresh, table_mask)