求助:使用OpenCV.js解析填字游戏网格遇轮廓识别问题
填字游戏网格解析优化方案
核心问题定位
方块内的数字会在Canny检测中产生额外边缘,导致cv.findContours把数字轮廓和方块轮廓混在一起,或者分割出破碎的方块区域,这是当前识别不全的主要原因。
优化后的处理流程
把阈值处理提前到高斯模糊之后、锐化之前,先消除数字的干扰,再做边缘检测和轮廓提取:
- 灰度转换:保持原有步骤,将彩色图转灰度图
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY) - 高斯模糊:用
cv.GaussianBlur平滑噪声,避免后续阈值处理出现过多噪点 - 二值化阈值处理:使用自适应阈值或全局阈值,把白色方块(含数字)统一转为白色,黑色方块转为黑色,直接消除数字的灰度差异:
- 全局阈值示例:
cv.threshold(gray, thresh, 200, 255, cv.THRESH_BINARY)(根据实际图像调整阈值,确保白色方块区域全为255) - 自适应阈值更适合光照不均的情况:
cv.adaptiveThreshold(gray, thresh, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 11, 2)
- 全局阈值示例:
- 形态学操作(可选):如果阈值后还有数字残留的小噪点,用腐蚀+膨胀组合(开运算)消除:
- 创建结构元素:
let kernel = cv.getStructuringElement(cv.MORPH_RECT, new cv.Size(3, 3)) - 开运算:
cv.morphologyEx(thresh, thresh, cv.MORPH_OPEN, kernel)
- 创建结构元素:
- 锐化(可选):如果阈值后的方块边缘不够清晰,再做锐化增强边缘
- Canny边缘检测:此时图像中只有方块的边缘,数字干扰已被消除,
cv.Canny(thresh, edges, 50, 150) - 轮廓提取:用
cv.findContours(edges, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE),注意用RETR_EXTERNAL只提取最外层轮廓,避免内部数字残留的小轮廓干扰
数字识别的分离处理
如果需要提取方块内的数字,不要和网格轮廓提取混在一起:
- 先完成上述网格轮廓提取,确定每个方块的坐标区域
- 对每个白色方块区域单独裁剪,再做数字识别(比如用轮廓提取数字,或者OCR),最后把数字标记到对应数组位置
关键注意点
- 阈值参数需要根据你的填字游戏图像实际调整,比如白色方块的灰度值如果接近255,全局阈值设为200左右就能把数字(灰度更低)和方块统一转为白色
- 形态学操作的结构元素大小不要太大,避免破坏方块的形状
- 轮廓提取时,通过轮廓的面积、宽高比过滤掉过小的噪点轮廓,只保留符合方块尺寸的轮廓
内容的提问来源于stack exchange,提问作者James Satori-Brunet
相关产品推荐
相关产品推荐

