在openCV中,canny运算符的低阈值和高阈值是强制性的:
cvCanny(input,output,thresh1,thresh2)
在Matlab中,有一个自动计算的选项:
edge(input,'canny')
我已经研究过Matlab的代码代码,而这实际上并不是直接自动计算的。
您是否了解canny运算符的任何实现以及opencv的自动阈值计算?
感谢
答案 0 :(得分:45)
当我在寻找一种自动计算Canny阈值的方法时,我偶然发现了这个答案。
希望这有助于任何寻找确定Canny算法自动阈值的好方法的人......
如果您的图像由不同的前景和背景组成,则前景对象的边缘可以使用以下提取:
使用以下方法计算Otsu的阈值:
double otsu_thresh_val = cv::threshold(
orig_img, _img, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU
);
我们不需要_img
。我们只对otsu_thresh_val
感兴趣,但不幸的是,目前在OpenCV中没有允许您仅计算阈值的方法。
使用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 );
有关此内容的更多信息,请参阅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)
他们使用基本统计实施类似的解决方案,以确定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);