如何基于网格线分割图像为行,再执行OCR并存储结果?
图像按行分割(基于横向线条)实现步骤
一、图像预处理
先对图像做基础处理,突出分割线和文字区域:
- 转灰度图:消除颜色干扰,用OpenCV的
cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)实现。 - 二值化反转:将分割线转为黑色、背景转为白色,便于后续检测。推荐用OTSU自动阈值:
ret, thresh_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
二、检测横向分割线
通过形态学操作强化线条,再提取分割位置:
- 创建水平结构核:用
cv2.getStructuringElement(cv2.MORPH_RECT, (width, 1)),其中width设为比单行长文字更宽的数值(比如50,可根据图像调整),目的是把断裂的横向线条连为完整的线。 - 闭运算强化线条:用
cv2.morphologyEx(thresh_img, cv2.MORPH_CLOSE, kernel),填补线条的缝隙,让分割线更连续。 - 提取分割线轮廓:
contours, _ = cv2.findContours(closed_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - 筛选并排序分割线y坐标:遍历轮廓,只保留高度极小的(比如高度<5)水平轮廓,提取每个轮廓的顶部y坐标,然后排序得到有序的分割位置列表。
三、分割图像为单行区域
- 补全边界:把图像顶部(y=0)和底部(y=图像高度)加入分割坐标列表,形成完整的行边界:
y_boundaries = [0] + sorted_line_ys + [original_img.shape[0]] - 逐行裁剪:遍历相邻的y边界,裁剪对应区域:
最终row_images = [] for i in range(len(y_boundaries)-1): top_y = y_boundaries[i] bottom_y = y_boundaries[i+1] row_img = original_img[top_y:bottom_y, :] row_images.append(row_img)row_images就是分割好的每行图像,直接用于后续OCR即可。
关键调整点
- 如果分割线检测不全,增大结构核的
width值;如果误把文字当成分割线,缩小width或严格限制轮廓高度。 - 若二值化效果差,可尝试手动设置阈值,替换OTSU自动阈值。
内容的提问来源于stack exchange,提问作者user18025483
相关产品推荐
相关产品推荐

