OpenCV数独单元格提取实现及水平垂直线检测问题优化
数独独立小方格提取的最佳实现方案
当前现有逻辑的问题
- 用Sobel算子加闭运算分离水平/垂直线的流程存在固有缺陷:流程中会把网格内的数字边缘、背景噪声都识别为有效线条,最终得到的线条图杂乱,无法支撑准确的方格分割。
- 霍夫线变换采用通用参数,没有匹配数独网格9x9等距的结构特性:当前的
minLineLength、maxLineGap参数适配性差,既会把不连续的杂边误判为网格线,也会漏掉本该连续的网格线段,导致线条检测结果不准。
高鲁棒性的实现流程
不需要先遍历找线条交点,利用数独网格天生为9x9等距矩形的先验特性做分割,实现难度和准确率都远优于交点定位法,具体步骤如下:
1. 纯净提取水平、垂直网格线
替换现有findVerticalLines和findHorizontalLines的实现,不用Sobel梯度计算,直接用形态学开运算过滤杂边,只保留连续的网格线:
传入的输入是已经精准抠出的完整数独外框ROI,先转成二值图,反转黑白让网格线为白色、背景为黑色,再执行以下代码:
def get_vertical_lines(grid_binary): h, w = grid_binary.shape # 核高度设置为单元格高度的1.5倍,仅保留能跨多格的长垂直线,过滤短边缘 kernel_len = int(h / 9 * 1.5) vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, kernel_len)) vertical_lines = cv2.morphologyEx(grid_binary, cv2.MORPH_OPEN, vertical_kernel, iterations=2) return vertical_lines def get_horizontal_lines(grid_binary): h, w = grid_binary.shape kernel_len = int(w / 9 * 1.5) horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_len, 1)) horizontal_lines = cv2.morphologyEx(grid_binary, cv2.MORPH_OPEN, horizontal_kernel, iterations=2) return horizontal_lines
2. 定位所有网格线的坐标位置
不用计算线条交点,直接用像素投影定位9条竖线、9条横线的位置:
- 对提取到的垂直线图,按列累加白色像素值,生成垂直投影数组,投影值显著偏高的列就是垂直线所在的列坐标。
- 对提取到的水平线图,按行累加白色像素值,生成水平投影数组,投影值显著偏高的行就是水平线所在的行坐标。
- 对两个投影数组做峰值检测,过滤掉同一条线上的连续相邻像素点,最终精准得到9个竖线x坐标、9个横线y坐标。
简化的峰值检测代码如下:
# 垂直投影定位竖线x坐标 vertical_proj = np.sum(vertical_lines, axis=0) x_coords = [] threshold = np.max(vertical_proj) * 0.3 for x in range(len(vertical_proj)): if vertical_proj[x] > threshold: if len(x_coords) == 0 or x - x_coords[-1] > 5: x_coords.append(x) # 水平投影定位横线y坐标,逻辑同垂直投影 horizontal_proj = np.sum(horizontal_lines, axis=1) y_coords = [] threshold = np.max(horizontal_proj) * 0.3 for y in range(len(horizontal_proj)): if horizontal_proj[y] > threshold: if len(y_coords) == 0 or y - y_coords[-1] > 5: y_coords.append(y)
3. 切分独立小方格
拿到9个竖线x坐标、9个横线y坐标后,相邻两个x值、相邻两个y值围成的矩形,就是一个独立小方格的ROI,直接从原始数独网格图上抠取即可,最终得到全部9*9=81个方格图像。
方案优势
- 不需要计算线条交点,避免了交叉点漏检、坐标计算误差的问题。
- 依托数独本身9x9等距结构的先验,就算网格线有轻微断裂,只要投影值达到阈值就能准确定位,鲁棒性远高于霍夫线变换、Sobel检测的方案。
- 不需要反复调试霍夫变换的多组参数,只要数独外框ROI提取准确,基本不会出现分割错误。
内容的提问来源于stack exchange,提问作者Janak Vaghasiya
相关产品推荐
相关产品推荐

