opencv Canny边缘检测用法

电脑杂谈  发布时间:2019-09-11 13:03:10  来源:网络整理

canny边缘检测原理_canny边缘检测 opencv_opencv canny 参数

一. Canny基本思想

1. 边缘检测

解析:边缘是对象和背景之间的界限,还能表示重叠对象之间的界限。边缘测试是图像分割的一部分,图像分割的目的是辨别出图像中的区域。边缘测试是定位边缘像素的过程,而边缘增强是提高边缘和背景之间的对比度以便进而更明白地认清边缘的过程。边缘跟踪是沿着边缘进行跟踪的过程,这个过程一般会把边缘像素采集到一个列表中,链码算法是边缘跟踪算法的一个特例。

2. 最优边缘准则 [1]

Canny边缘检测算子是John F. Canny于1986年开发起来的一个多级边缘测试算法。Canny的目标是找到一个最优的边缘测试算法,最优边缘检测的含义,如下所示:

(1)最优检测:算法就能尽可能多地标识出图像中的实际边缘,漏检真实边缘的几率和误检非边缘的几率都尽可能小;

(2)最优定位准则:检测到的边缘点的位置距离实际边缘点的位置近期,或者是因为噪声影响导致测试出的边缘偏离物体的真实边缘的程度最小;

(3)检测点与边缘点一一对应:算子检测的边缘点与实际边缘点需要是一一对应。

二. Canny算法实现

1. 高斯滤波图像去噪

canny边缘检测 opencv_opencv canny 参数_canny边缘检测原理

垃圾进,垃圾出,数据预处理工作是比较重要的,图像处理也不例外。这里使用高斯滤波进行图像去噪,比如blur = cv2.GaussianBlur(img, (5,5), 0)canny边缘检测 opencv,处理后的图像与原始图像相比稍微有些模糊。这样单独的一个像素噪声在经过高斯滤波的图像上更加几乎没有影响。

2. 计算图像梯度

Canny算法的基本思想是寻找一幅图相中灰度强度差异最强的位置。所谓差异最强,即指梯度方向。对平滑后的图像使用Sobel算子计算水准方向和竖直方向的一阶导数(图像梯度)()。根据得到的这两幅梯度图()找到边界的梯度和方向。如下所示:

梯度的方向通常总是与界限垂直。梯度方向被归为四类:垂直,水平,和两个对角线。

3. 非极大值抑制

在获取梯度的方向和大小然后canny边缘检测 opencv,应该对整幅图像做一个扫描,去除这些非边界上的点。对每一个像素进行检查,看这个点的梯度是不是周围带有同样梯度方向的点中最大的。如下所示:

上图中的数字代表了像素点的梯度密度,箭头方向代表了梯度方向。以第二排第三个像素点为例,由于梯度方向向下,则将这一点的效率(7)与其上下两个像素点的强度(5和4)比较,由于这一点强度最大,则保留。

opencv canny 参数_canny边缘检测原理_canny边缘检测 opencv

4. 滞后阈值

现在要确认这些界限才是真正的边界。这时我们应该修改两个阈值:minVal和maxVal。当图像的灰度梯度低于maxVal时被觉得是真的界限,那些超出minVal的界限会被放弃。如果介于二者之间的话,就要看这个点能否与某个被确认为真正的界限点相连,如果是就觉得它也有边界点,如果不是就放弃。如下所示:

A高于阈值maxVal所以是真正的界限点,C虽然超出maxVal但低于minVal并且与A相连,所以也被觉得是真正的界限点。而B就会被放弃,因为它除了超过maxVal而且不与真正的界限点相连。所以选用适合的maxVal和minVal对于如何受到好的结果比较重要。在这一步一些小的噪声点也会被除去,因为我们假定边界都是一些长的线段。

三. Canny代码应用

[python]view plain

importcv2importnumpyasnpif__name__=='__main__':defnothing(*arg):passcv2.namedWindow('edge')cv2.createTrackbar('thrs1','edge',2000,5000,nothing)cv2.createTrackbar('thrs2','edge',4000,5000,nothing)cap=cv2.VideoCapture(0)whileTrue:flag,img=cap.read()img=cv2.GaussianBlur(img,(3,3),0)gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)thrs1=cv2.getTrackbarPos('thrs1','edge')thrs2=cv2.getTrackbarPos('thrs2','edge')edge=cv2.Canny(gray,thrs1,thrs2,apertureSize=5)vis=img.copy()vis=np.uint8(vis/2.)vis[edge!=0]=(0,255,0)cv2.imshow('edge',vis)ch=cv2.waitKey(5)&0xFFifch==27:breakcv2.destroyAllWindows()

解析:

1. cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]) → edges

(1)其中较大的threshold2用于测量图像中显著的边缘,但通常状况下测试的效果不会那么完美,边缘检测下来是断断续续的,所以这时候用较小的threshold1用于将这种间断的边缘连接上去。

canny边缘检测 opencv_canny边缘检测原理_opencv canny 参数

(2)可选参数apertureSize是Sobel算子的大小(默认值为3),而参数L2gradient是一个布尔值,如果为真,则使用更准确的L2范数进行推导(即两个方向的倒数的平方和再开方),否则使用L1范数(直接将两个方向导数的绝对值相加)。

2.cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst

(1)ddepth表示图像的深度,-1表示采取的是与原图像同样的深度。目标图像的深度应该小于等于原图像的深度;

(2)dx和dy表示求导的阶数,0表示这个方向上没有求导,一般为0、1、2。

(3)ksize表示Sobel算子的大小,必须为1、3、5、7。

(4)scale:optional scale factor for the computed derivative values; by default, no scaling is applied。

(5)delta:optional delta value that is added to the results prior to storing them in dst.

(6)borderType:pixel extrapolation method.

3. cv2.convertScaleAbs(src[, dst[, alpha[, beta]]]) → dst

(1)Scales, calculates absolute values, and converts the result to 8-bit, namelydst = src*alpha + beta.

canny边缘检测 opencv_canny边缘检测原理_opencv canny 参数

(2)alpha:optional scale factor.

(3)beta:optional delta added to the scaled values.

4.cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) → dst

(1)alpha表示src1的权重。

(2)beta表示src2的权重。

(3)gamma:scalar added to each sum.

(4)dtype:optional depth of the output array; when both input arrays have the same depth, dtype can be set to -1, which will be equivalent to src1.depth().

cv2.addWeighted表示计算两个数组的权重和,即dst = src1*alpha + src2*beta + gamma。

说明:边缘测试常见方式:Canny算子,Sobel算子,Laplace算子,Scharr滤波器。

参考文献:

[1]Canny算法:

[2]OpenCV官方教程中文版

[3]opencv-Python教程:


本文来自电脑杂谈,转载请注明本文网址:
http://xinshanjie.com/a/jisuanjixue/article-122516-1.html

    相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...