OpenCV - 精明的边缘检测无法正常工作

Posted

技术标签:

【中文标题】OpenCV - 精明的边缘检测无法正常工作【英文标题】:OpenCV - canny edge detection not working properly 【发布时间】:2017-06-13 01:54:16 【问题描述】:

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

原始图像 -> 灰度图像 -> 高斯模糊 -> Canny边缘检测 -> 寻找轮廓 -> 绘制轮廓

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

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

我对此进行了很多研究,发现问题在于精明的边缘检测,下面是精明的图像:

如您所见,边缘检测没有完美链接,并且在某些点上没有连接边缘。这就是原因。

我在 How to select the best set of parameters in Canny Edge detection algorithm implemented in OpenCV? 遇到过类似的问题 我遵循了解决方案,但它对我不起作用。

我的canny检测代码如下:

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

我不知道我错在哪里!我应该怎么做才能完美地检测到文档?

【问题讨论】:

为了增强边缘使用形态膨胀。见THIS PAGE。 【参考方案1】:

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

使用下面的sn-p:

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 值通常被统计学家用于数据科学。所以这里也考虑一下。

这是我得到的:

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

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

:)

【讨论】:

我是用大津的方法动态查找阈值的。我也应用了您的解决方案,但没有奏效,并且降低了相机帧数。 你的意思是寻找边缘很慢? 不,我的意思是相机预览帧由于阈值计算而变慢 这可能是因为它正在计算图像的中值并根据该值设置阈值 是的,它会降低相机预览的性能。顺便说一句,感谢您的努力。您还有其他解决方案吗?【参考方案2】:

对 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 滤波器,因为阴影和光线的影响在图像的各个部分可能会有很大差异

【讨论】:

感谢您的努力,但我不再从事此项目,将检查您的解决方案并稍后回复您。

以上是关于OpenCV - 精明的边缘检测无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV基础(11)基于OpenCV的边缘检测

如何针对低分辨率/模糊素材优化 OpenCV 的 Canny 边缘检测

使用 OpenCV python 在一个窗口中结合多个 Canny 边缘检测

自适应 Canny 边缘检测

python 精明等边缘检测的方法

OpenCV4中调用HED边缘检测算法