首页 文章

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

提问于
浏览
1

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

Original image - > Gray scale image - > GaussianBlur - > Canny edge detection - > finding contours - > draw Contours

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

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 回答

  • 1

    首先,执行 Canny edge detection 的方法必须改变 . 您在 cv2.Canny() manually 中设置了更低和更高的阈值 . 您可以自动执行此操作 . 我用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)
    

    So what am I doing here?

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

    这就是我得到的:

    enter image description here

    为了增强这个边缘信息,我使用 cv2.MORPH_CROSS 内核执行了 morphological dilation

    enter image description here

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

    :)

  • 4

    通过对Jeru Luke发布的算法的小改编,我得到了更好的结果 .

    在文档检测上,我们宁愿搜索文档的暗阴影边缘:

    • 对于浅色图像,与白纸一样,中位数较高且"255 - median"表现优于中位数

    • 对于小值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);
        }
    

    另外,对于某些文档,可以改进结果

    • 使用中值滤波器后锐化图像

    • 使用更强的中值滤波器

    • 计算中位数并对图像的单独部分执行精确过滤,因为阴影和光线影响可能在图像的某些部分上有很大差异

相关问题