3

我正在 Android 平台上创建数独解决应用程序,并且在处理图像时遇到了问题。我正在尝试使用 OpenCV 使用 Sobel 过滤器找到拼图的水平线,然后使用 Otsu 算法进行阈值处理:

Mat kernaly = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(10,2));
Mat dy = new Mat();
Mat close = new Mat();
Imgproc.Sobel(img, dy, CvType.CV_16S, 0, 2);
Core.convertScaleAbs(dy, dy);
Core.normalize(dy,dy,0,255,Core.NORM_MINMAX);
Imgproc.threshold(dy, close, 0, 255, Imgproc.THRESH_BINARY|Imgproc.THRESH_OTSU);
Imgproc.morphologyEx(close, close, Imgproc.MORPH_DILATE, kernaly);

这种方法实际上适用于大多数图像,例如:

在此处输入图像描述

但是,以下图像失败:

在此处输入图像描述

有人可以解释为什么结果如此不同,而上面的第二张图片只返回一行吗?另外,我是否应该只使用另一种方法,例如 Canny 或 Hough 线?

提前致谢!


编辑:使用 marol 的建议,我尝试尽可能多地删除黑色边框,而不必扭曲图像。这是将上述相同过程应用于这些重新处理的图像时的结果。

图 1:

图 1

图 2:

图 2

如您所见,结果更好,因为已检测到大多数行。但是,它仍然不够好。它可以通过添加一个固定的阈值来改进,但是对于每个图像来说必须是不同的。

我可能会使用一种新方法,因为这种方法似乎不够健壮。任何提示将不胜感激。

4

3 回答 3

1

替代 otsu 的替代建议:

您可以在 sobel 图像中搜索 Y 方向的局部最大值。

  • 使用 1x10 矩形内核扩展 sobel 图像(“10”应该是图像中网格线之间的最小距离)
  • 将扩张后的图像与原始图像进行比较,将所有不相等的像素设置为零 ( cmp(dy,dilatedImg,comparisonImg,CMP_GE)
  • 删除没有任何局部最大值的所有区域 ( threshold(dy, mask, 1, 255, THRESH_BINARY); And(comparisonImg, mask, comparisonImg);)

现在,您拥有了与局部区域中最强水平边缘相对应的所有像素。


旁注,您对 sobel 的使用有点奇怪:

您使用第二个索贝尔派生词,Imgproc.Sobel(img, dy, CvType.CV_16S, 0, 2); 我假设您这样做是因为您想识别黑线的中心,而不是它们的边界。但在这种情况下,下一步,convertScaleAbs,似乎违反直觉。这样你就可以得到第二个 sobel 导数的最小值和最大值。最大值应该对应于黑线的中心,但最小值会在边缘图像中引入奇怪的“三重线”伪影。如果您使用第一个 sobel 导数,Abs 步骤会更合理,但在您的情况下,丢弃负值可能会更好。

于 2014-08-09T08:14:34.797 回答
1

该问题可能是由于强度分布引起的。如果您查看 sobel 运算符后的直方图:

在此处输入图像描述

将其与成功 otsu 检测的图像直方图进行比较:

在此处输入图像描述

您可以很容易地在第一个直方图中看到失败,因为计算的阈值是向右移动而不是向左移动(即使左侧的主要峰值对于所有黑色像素都非常突出)。而在第二种情况下,分布并没有被划分为峰值和平坦的其余部分,而不是我们有更多的白色像素“携带”计算的阈值向右。

换句话说,你必须摆脱黑色像素的统治。换句话说,尝试缩放数独,使周围的黑色像素边框尽可能小。这将使分布更像第二种情况。

恕我直言,从这些直方图中您可以说该方法非常敏感,因为图像中“黑色”和“白色”部分之间的差异,因此计算的阈值水平对图像非常敏感。我不会依赖这种方法。一些固定的阈值水平呢?在一般情况下听起来可能不太好,但在这里它可能更具确定性并且仍然正确。

于 2014-08-08T13:10:31.203 回答
0

我找到了一个快速修复,通过在运行上面的代码之前进行一些图像处理,可以显着改善结果:

  1. 我只是按照marol上面的建议做了,尽可能多地剪掉黑色边框。
  2. 使用 warpPerspective 调整图像大小,使其成为标准尺寸的正方形。
  3. 运行上面的代码,然后扩大结果。

它不是最强大的解决方案,但它适用于我的所有 10 个测试图像样本。

于 2014-08-14T02:57:15.997 回答