OpenCV - 从数独谜题中删除网格线

时间:2012-11-08 01:07:41

标签: image-processing opencv sudoku

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

  • 自适应阈值拼图
  • 扩张以减少要考虑的轮廓数量
  • 找到拼图的轮廓并将其扭曲成正方形
  • 将广场划分为81个相等的单元格;寻找至少20%白色像素的细胞
  • 找到最接近这些单元格中心的白色斑点并获取其边界矩形
  • 在边界矩形内的图像部分使用字符识别(k-最近邻/ Tesseract /等)

虽然我可以使用简单的填充物去除数独拼图的厚外边框,但内部网格线即使在扩张后也不是连续的,并且不能如此容易地移除。为了说明,这里是删除外部网格线后的数独示例:

enter image description here

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

enter image description here

我考虑过扭曲图像以降低内部网格线的可见性。我可以使用Hough变换或this post中描述的方法来找到网格线作为unwarping的前奏。但是,我没有看到任何其他显着的好处,并且应该更安全,更容易完全删除网格线。

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

    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);

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

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

非常感谢。

2 个答案:

答案 0 :(得分:2)

如果你不想做一个正确的unwarp,那么使用较小的单元格进行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,具体取决于网格线与数字的厚度。

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

如果所有这些方法都失败了,为了进行填充,无论如何你都必须获得网格线的扭曲,所以你不妨进行整理

答案 1 :(得分:2)

查看此博客帖子以获得一个好的解决方案 http://www.aishack.in/2010/08/sudoku-grabber-with-opencv/