在opencv中自动计算Canny操作的低和高阈值

时间:2010-11-27 15:05:39

标签: image-processing opencv

在openCV中,canny运算符的低阈值和高阈值是强制性的:

cvCanny(input,output,thresh1,thresh2)

在Matlab中,有一个自动计算的选项:

edge(input,'canny')

我已经研究过Matlab的代码代码,而这实际上并不是直接自动计算的。

您是否了解canny运算符的任何实现以及opencv的自动阈值计算?

感谢

7 个答案:

答案 0 :(得分:45)

当我在寻找一种自动计算Canny阈值的方法时,我偶然发现了这个答案。

希望这有助于任何寻找确定Canny算法自动阈值的好方法的人......


如果您的图像由不同的前景和背景组成,则前景对象的边缘可以使用以下提取:

  1. 使用以下方法计算Otsu的阈值:

    double otsu_thresh_val = cv::threshold(
        orig_img, _img, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU
    );
    

    我们不需要_img。我们只对otsu_thresh_val感兴趣,但不幸的是,目前在OpenCV中没有允许您仅计算阈值的方法。

  2. 使用Otsu的阈值作为更高的阈值,使用Canny算法的下限阈值的一半。

    double high_thresh_val  = otsu_thresh_val,
           lower_thresh_val = otsu_thresh_val * 0.5;
    cv::Canny( orig_img, cannyOP, lower_thresh_val, high_thresh_val );
    
  3. 有关此内容的更多信息,请参阅this paper: The Study on An Application of Otsu Method in Canny Operator。可以找到对Otsu实施的解释here

答案 1 :(得分:16)

您可以使用输入灰度图像的平均值,并使用标准偏差定义下限和上限阈值。 您可以在此处获得更详细的解释和opencv代码: http://www.kerrywong.com/2009/05/07/canny-edge-detection-auto-thresholding/

答案 2 :(得分:7)

此外,还有一些代码可以通过将其放入OpenCV构建中来自动执行此操作。我在OpenCV用户邮件列表中找到了它,所以没有保证。 :)

讨论:http://opencv-users.1802565.n2.nabble.com/Automatic-thresholding-in-cvCanny-td5871024.html GitHub(代码):https://gist.github.com/756833

答案 3 :(得分:4)

点击此链接:http://www.pyimagesearch.com/2015/04/06/zero-parameter-automatic-canny-edge-detection-with-python-and-opencv/

他们使用基本统计实施类似的解决方案,以确定Canny边缘检测的低和高阈值。

def auto_canny(image, sigma=0.33):
     # compute the median of the single channel pixel intensities
     v = np.median(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(image, lower, upper)

    # return the edged image
    return edged

答案 4 :(得分:3)

我查看了Matlab Canny边缘检测的源代码,并设法用OpenCV 3用Java编写。

library(dplyr)
df %>% 
   filter(name %in% c("A", "C")) %>% 
   group_by(type) %>% 
   summarise(name = 'AC', val = sum(val)) %>% 
   full_join(df, ., on = 'type') %>% 
   arrange(type, val)
#    name type val
#1    A   10   1
#2    B   10   2
#3    C   10   3
#4   AC   10   4
#5    A   20   4
#6    B   20   5
#7    C   20   6
#8   AC   20  10

文件路径是保存输出图像的位置。并且输入图像应该是具有U8数据类型的灰度图像。 基本原理是通过亮度排除nonEdgeRate(60%)像素作为非边缘像素。直方图用于对亮度进行排序,并且将设置上阈值,使其下方有60%的像素。通过将上限阈值乘以thresholdRate(0.6)来设置下限阈值。

请注意,在我的特定用例中,我自己调整了double nonEdgeRate = 0.6和double thresholdRate = 0.6。在matlab中,原始值分别为0.7和0.4。

答案 5 :(得分:1)

我有另一种解决同样问题的方法。该解决方案还涉及选择边缘检测的最佳阈值。

  • 首先计算灰度图像的中值
  • 根据中位数选择两个值(下阈值和上阈值) 灰度图像的值。

以下伪代码向您展示了它的完成方式:

v = np.median(gray_img)
sigma = 0.33

#---- apply optimal Canny edge detection using the computed median----
lower_thresh = int(max(0, (1.0 - sigma) * v))
upper_thresh = int(min(255, (1.0 + sigma) * v))

将这些阈值修复为canny边缘检测功能中的参数。

插图:如果在统计中观察到高斯曲线,则在分布中考虑曲线两侧的0.33之间的值。假设这些点之外的任何值都是异常值。由于图像被认为是数据,因此这里也假设了这个概念。

答案 6 :(得分:0)

正如Luca Del Tongo建议的那样,您可以根据灰度图像计算阈值,例如:在Java中使用OpenCV ...

MatOfDouble mu = new MatOfDouble();
MatOfDouble stddev = new MatOfDouble();
Core.meanStdDev(greyMat, mu, stddev);
threshold1 = mu.get(0, 0)[0];
threshold2 = stddev.get(0, 0)[0];
Imgproc.Canny(greyMat, outputMat, threshold1, threshold2);