如何使用OpenCV从图像中识别矩阵的行列维度
基于OpenCV识别井字棋类矩阵的行列维度方法
一、图像预处理
先对输入图像做基础预处理,统一格式并突出线条特征:
- 读取图像后转为灰度图:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - 用自适应二值化处理,适配不同光照下的图像:
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) - 执行形态学闭操作,消除噪点同时保留线条结构:
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3)) processed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
二、分离并计数横竖线条
提取横向线条并计算行数
横向线条决定矩阵的行数,通过形态学操作单独提取:
- 创建横向结构元素,宽度设为图像宽度的1/20(可根据实际图像调整):
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (img.shape[1]//20, 1)) - 提取横向线条:
horizontal_lines = cv2.morphologyEx(processed, cv2.MORPH_OPEN, horizontal_kernel, iterations=2) - 检测横向线条的轮廓,收集每条线条的平均y坐标,排序后去重(相邻线条距离小于阈值视为同一条):
horizontal_contours, _ = cv2.findContours(horizontal_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) horizontal_y = [cnt[:,0,1].mean() for cnt in horizontal_contours] horizontal_y.sort() filtered_h = [] threshold = img.shape[0]//50 for y in horizontal_y: if not filtered_h or abs(y - filtered_h[-1]) > threshold: filtered_h.append(y) - 矩阵行数
M = len(filtered_h) - 1(线条数量比格子行数多1)
提取纵向线条并计算列数
纵向线条决定矩阵列数,操作逻辑和横向一致:
- 创建纵向结构元素,高度设为图像高度的1/20:
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, img.shape[0]//20)) - 提取纵向线条:
vertical_lines = cv2.morphologyEx(processed, cv2.MORPH_OPEN, vertical_kernel, iterations=2) - 检测纵向线条轮廓,收集平均x坐标并去重:
vertical_contours, _ = cv2.findContours(vertical_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) vertical_x = [cnt[:,0,0].mean() for cnt in vertical_contours] vertical_x.sort() filtered_v = [] threshold = img.shape[1]//50 for x in vertical_x: if not filtered_v or abs(x - filtered_v[-1]) > threshold: filtered_v.append(x) - 矩阵列数
N = len(filtered_v) - 1
三、优化方案
- 如果图像存在透视畸变,先通过透视变换校正为正视图,再执行上述步骤,保证线条水平垂直
- 可计算相邻线条的平均间距,过滤掉间距远大于平均值的异常线条,提升计数准确性
内容的提问来源于stack exchange,提问作者DHANUSH T
相关产品推荐
相关产品推荐

