opencv - Sobel 滤波图像上的 Otsu 阈值处理给出不同的结果

标签 opencv image-processing sudoku threshold sobel

我正在 Android 平台上创建数独解决应用程序,但在处理图像时遇到了问题。我正在尝试使用 Sobel 过滤器使用 OpenCV 找到拼图的水平线,然后使用 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);

这个方法其实对大多数图片都适用,例如:

enter image description here

但是,对于下面的图片,它失败了:

enter image description here

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

提前致谢!


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

图 1:

Image 1

图 2:

Image 2

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

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

最佳答案

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

enter image description here

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

enter image description here

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

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

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

关于opencv - Sobel 滤波图像上的 Otsu 阈值处理给出不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25202260/

相关文章:

c++ - 为什么我过滤后的图像(应该是二进制的)仍然包含彩色部分?(OpenCV in C++)

types - 将IplImage类型IPL_LABEL转换为IplImage类型IPL_DEPTH_8U

python - 如何使用OpenCV从mp4从mp4创建帧数组

python - PyCharm 在 __init__.py 中找不到任何 OpenCV 函数的引用

c++ - cv::erode 导致错误:OpenCV 错误:Mat 中的断言失败(m.dims >= 2)

php - 使用 PHP 将分辨率转换为纵横比

python - libvips 最近邻/双三次深度缩放金字塔创建

c - 蛮力数独求解器 : backtracking?

java - 如何在 Java 中重用一个线程?

C++为什么结构对象值在循环结束时重置回零