OpenCV - canny边缘检测无法正常工作

时间:2017-01-27 11:32:43

标签: opencv image-processing edge-detection opencv4android

我是Android的OpenCV新手。我目前正在研究文档检测演示应用程序。到目前为止我所做的如下:

原始图片 - > 灰度图像 - > GaussianBlur - > Canny边缘检测 - > 寻找轮廓 - > 绘制轮廓

我能够完美地检测出纸张,如下图所示。

enter image description here

但它没有检测到某些文件。以下是其中一个

enter image description here

我对此进行了大量研究,发现问题在于精确边缘检测,下面是精确图像:

enter image description here

正如您所看到的,边缘检测并未完美链接,并且在某些时候不会连接边缘。这就是原因。

我在How to select the best set of parameters in Canny Edge detection algorithm implemented in OpenCV?处遇到了类似的问题 我已经按照解决方案但它对我没有用。

我的精确检测代码如下:

double otsu_thresold = Imgproc.threshold(mGray,edged,0,255, Imgproc.THRESH_OTSU);
Imgproc.Canny(mRgba, edged, otsu_thresold*0.5,otsu_thresold);

我不知道我哪里错了!我该怎么做以完美地检测文件?

2 个答案:

答案 0 :(得分:4)

首先,执行 Canny边缘检测的方法必须改变。您在cv2.Canny() 手动设置的阈值越来越低。您可以自动执行此操作。我使用THIS LINK作为参考。

使用以下代码段:

v = np.median(gray_image)

#---- apply automatic Canny edge detection using the computed median----
lower = int(max(0, (1.0 - sigma) * v))
upper = int(min(255, (1.0 + sigma) * v))
edged = cv2.Canny(gray_image, lower, upper)
cv2.imshow('Edges',edged)

那我在这做什么?

我正在拍摄灰度图像的中值值。选择sigma值0.33来设置lowerupper阈值。 0.33 值通常由统计人员用于数据科学。所以这里也考虑到了。

这就是我得到的:

enter image description here

为了增强此边缘信息,我使用cv2.MORPH_CROSS内核执行形态膨胀

enter image description here

现在只需执行常规cv2.findContours()操作并绘制最大轮廓。

:)

答案 1 :(得分:1)

仅对Jeru Luke发布的算法进行少量修改,我的结果就会更好。

在文档检测中,我们宁愿搜索文档的深色阴影边缘:

  • 对于浅色图像(如白皮书),中位数较高,“ 255-中位数”的效果要好于仅中位数
  • 对于较小的值,sigma太小而无法产生足够宽的范围。

这是我的C#算法:

    double s = 0.33;
    if (imageMedian > 191) // light images
    {
      cannyTh1 = (int)Math.Max(0, (1 - 2*s) * (255 - imageMedian));
      cannyTh2 = (int)Math.Max(85, (1 + 2*s) * (255 - imageMedian));
    }
    else if (imageMedian > 127)
    {
      cannyTh1 = (int)Math.Max(0, (1 - s) * (255 - imageMedian));
      cannyTh2 = (int)Math.Min(255, (1 + s) * (255 - imageMedian));
    }
    else if (imageMedian < 63) // dark images
    {
      cannyTh1 = (int)Math.Max(0, (1 - 2*s) * imageMedian);
      cannyTh2 = (int)Math.Max(85, (1 + 2*s) * imageMedian);
    }
    else
    {
      cannyTh1 = (int)Math.Max(0, (1 - s) * imageMedian);
      cannyTh2 = (int)Math.Min(255, (1 + s) * imageMedian);
    }

此外,某些文档的结果可以通过以下方式得到改善

  • 使用中值滤镜后对图像进行锐化
  • 使用更强的中值滤波器
  • 计算中位数,并对图像的各个部分执行canny滤波,因为阴影和光的影响在图像的各个部分上可能有很大差异
相关问题