algorithm - Canny边缘检测算法——实现问题

标签 algorithm image-processing edge-detection

我正在尝试实现 Canny 边缘检测算法,但在此过程中遇到了一些问题。我想我了解 Canny 边缘检测的每一步,但是与 OpenCv 实现给出的结果相比,它们相差很大。

似乎我无法像算法应该产生的那样获得 1px 宽的边缘。以下是这个非常简单的二进制图像的步骤和结果:

正在处理的二值图像:

Binary Image that is being processed

使用 Sobel 算子计算的梯度大小:

Gradient magnitudes

边缘方向:

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 <br>
1 / - - - - - - - - - - - \ 1   <br>
1 | / - - - - - - - - - \ | 1  <br>
1 | | / - - - - - - - \ | | 1  <br>
1 | | | / - - - - - \ | | | 1  <br>
1 | | | | | | | | | | | | | 1  <br>
1 | | | | | | | | | | | | | 1  <br>
1 | | | | | | | | | | | | | 1 <br>
1 | | | | | | | | | | | | | 1 <br>
1 | | | | | | | | | | | | | 1 <br>
1 | | | \ - - - - - / | | | 1 <br>
1 | | \ - - - - - - - / | | 1 <br>
1 | \ - - - - - - - - - / | 1 <br>
1 \ - - - - - - - - - - - / 1 <br>
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 

非最大值抑制图像:

0   0   0   0   0   0   0   0   0   0   0   0   0   0   0<br>
0   0   0   0   0   0   0   0   0   0   0   0   0   0   0<br>
0   0 255   0   0   0   0   0   0   0   0   0 255   0   0<br>
0   0   0   0   0   0   0   0   0   0   0   0   0   0   0<br>
0   0   0   0 255   0   0   0   0   0 255   0   0   0   0<br>
0   0   0   0   0   0   0   0   0   0   0   0   0   0   0<br>
0   0   0   0   0   0   0   0   0   0   0   0   0   0   0<br>
0   0   0   0   0   0   0   0   0   0   0   0   0   0   0<br>
0   0   0   0   0   0   0   0   0   0   0   0   0   0   0<br>
0   0   0   0   0   0   0   0   0   0   0   0   0   0   0<br>
0   0   0   0 255   0   0   0   0   0 255   0   0   0   0<br>
0   0   0   0   0   0   0   0   0   0   0   0   0   0   0<br>
0   0 255   0   0   0   0   0   0   0   0   0 255   0   0<br>
0   0   0   0   0   0   0   0   0   0   0   0   0   0   0<br>
0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

如果我在这一步执行滞后阈值处理,我会得到非常粗的结果。明显的问题是梯度幅度值,但我不知道如何解决它。如果有经验和知识渊博的人愿意为我指明正确的方向,我将不胜感激。

最佳答案

我认为 Sobel 运算符不适合您的情况。实际上,梯度幅度应该已经粗略勾勒出边缘。后面的步骤正在完善边缘提取。我不确定你是如何实现细化过程的,我所做的是使用插值来找到梯度范数为局部最大值的像素。当我应用 Sobel 算子时,我没有得到很厚的边缘,但边缘在某些点上不是很连续:

0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
 0     0     0     0   270   270   270   270   270   270   270   270     0     0     0     0
 0     0     0   270     0     0     0     0     0     0   270   270     0     0     0     0
 0     0   270     0     0     0     0     0     0     0     0     0     0     0   270     0
 0     0   270     0     0   270   270   270   270     0     0   270     0     0   270     0
 0     0   270     0     0   270     0     0     0     0     0   270     0     0   270     0
 0     0   270     0     0   270     0     0     0     0     0   270     0     0   270     0
 0     0   270     0     0   270     0     0     0     0     0   270     0     0   270     0
 0     0   270     0     0     0     0     0     0     0     0   270     0     0   270     0
 0     0   270   270     0     0     0     0     0     0     0   270     0     0   270     0
 0     0   270   270     0   270   270   270   270   270   270   270     0     0   270     0
 0     0     0     0     0     0     0     0     0     0     0     0     0   270   270     0
 0     0     0     0     0     0     0     0     0     0     0     0   270   270     0     0
 0     0     0     0   270   270   270   270   270   270   270   270   270     0     0     0
 0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0

当我使用高斯函数的标准差对原始图像进行卷积以获得梯度时,我终于可以得到清晰的细边:

0     0     0     0     0     0     0     0     0     0     0     0     0     0
 0     1   494   494   494   494   494   494   494   494   494   494     1     1
 0   494     1     1     1     1     1     1     1     1     1     1   494     1
 0   494     1     1   494   494   494   494   494   494     1     1   494     1
 0   494     1   494   494     1     1     1     1   494   494     1   494     1
 0   494     1   494     1     1     1     1     1     1   494     1   494     1
 0   494     1   494     1     1     1     1     1     1   494     1   494     1
 0   494     1   494     1     1     1     1     1     1   494     1   494     1
 0   494     1   494     1     1     1     1     1     1   494     1   494     1
 0   494     1   494   494     1     1     1     1   494   494     1   494     1
 0   494     1     1   494   494   494   494   494   494     1     1   494     1
 0   494     1     1     1     1     1     1     1     1     1     1   494     1
 0     1   494   494   494   494   494   494   494   494   494   494     1     1
 0     1     1     1     1     1     1     1     1     1     1     1     1     1

关于algorithm - Canny边缘检测算法——实现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19334219/

相关文章:

ios - 如何使用 Swift 语法在 GPUImage2 中将两个图像混合在一起

python - 无法正确检测和遮盖轮廓

objective-c - iOS 上的 cv::HoughLines 失败并显示 'OpenCV Error: Assertion failed'

pow(float, float) 的算法

python - 具有 O(1) 随机移除和添加的数据结构,用于混洗生成器顺序

c - 返回给定数组中的最小唯一值 - C 语言

image - 图像检测中的线条和边缘有什么区别?

java - 获取具有目标总和的数组子集的算法无法正常工作

c# - 将 8BIM 配置文件元数据添加到 tiff 图像文件

c++ - Canny 边缘检测后查找轮廓