image-processing - OpenCV - 从数独游戏中删除网格线

标签 image-processing opencv sudoku

我正在编写一个 Android 应用程序来从图片中提取数独谜题。对于 9x9 数独网格中的每个单元格,我需要确定它是包含数字 1 到 9 之一还是空白。以下是我的算法的大纲:

  • 自适应阈值难题
  • 扩张以减少要考虑的轮廓数量
  • 找到拼图的轮廓并将其变形为正方形
  • 将正方形分成 81 个相等的单元格;寻找具有至少 20% 白色像素
  • 的单元格
  • 找到最靠近这些单元格中心的白色 Blob 并得到它的边界矩形
  • 对边界矩形内的图像部分使用字符识别(k-最近邻/Tesseract 等)

虽然我可以使用简单的填充填充去除数独游戏的粗外边界,但内部网格线并不连续,即使在膨胀后也是如此,并且不能轻易去除。为了便于说明,这里是移除外部网格线后的数独示例:

enter image description here

问题:有时,单元格中有足够多的网格线,超过 20% 的像素是白色的,因此我错误地检测到该单元格,因为其中有一个数字.这是此类单元格的示例:

enter image description here

我考虑过取消扭曲图像以降低内部网格线的可见性。我可以使用霍夫变换或 this 中描述的方法发布以查找网格线作为展开的前奏。然而,我没有看到任何其他显着的好处来取消扭曲,而且完全删除网格线应该更安全也更容易。

或者,我可以修改我的预处理,使内部网格线保持不变。目前我的预处理是:

    Imgproc.GaussianBlur(mat, mat, new Size(11,11), 0);
    Imgproc.adaptiveThreshold(mat, matBW, 255, 
        Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 5, 2);
    Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_CROSS, new Size(3, 3));
    Imgproc.dilate(matBW, matBW, kernel);

高斯模糊对于在阈值化之前减少噪声是必要的。扩张是为了确保外部网格线连接,但不足以重新连接内部线。

如何在不影响图像其余部分的情况下一致地移除内部网格线?

非常感谢。

最佳答案

如果您不想进行适当的反扭曲,可能值得使用较小的单元格进行 digit_present 测试。

假设左上角的单元格坐标为 (x1,y1,x2,y1)==(0,0,10,10)。您可以将新单元格定义为 (x1+k,y1+k,x2-k,y2-k), k=min(x2-x1,y2-y1)/4

另一种可能有效的策略是使用 erode在测试之前,取决于网格线与数字的粗细。

最后,您可以将所有单元格提供给您的分类器,并使用其置信度指数(如果有的话);如果分类器置信度太低,则可能不是数字。

如果所有这些方法都失败了,为了进行填充,您无论如何都必须获得网格线的翘曲,所以您也可以进行反翘

关于image-processing - OpenCV - 从数独游戏中删除网格线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13280952/

相关文章:

python - 使用 Raspberry Pi + Webcam 在 python 中录制视频,但有时相机没有像我预期的那样打开/关闭

python - Opencv和python获取正确的文档构建并绘制图像

python - 用于数独解题器的从水平行列表中获取部分的一种简短(呃)方法

opencv - 'W'上的字符分割失败

java - 安卓数独游戏,按下按钮使游戏崩溃

c - 该程序仅解决第一行[数独]

image-processing - OpenCV 目标检测 - 中心点

opencv - 如何使用OpenCV查找从摄像机到对象/标记的距离和旋转?

python - 如何提取图像中的绿色对象?

ios - 如何在 iOS 设备上滚动时保持动画 gif 动画?