Scharr 算子及函数应用
这个可以看作sobel 算子的改进版,速度相同,精度更高
dst = cv2.Scharr( src, ddepth, dx, dy[, scale[, delta[, borderType]]] )
再函数 cv2.Sobel() 中 ksize=-1 ,就会使用Scharr滤波器。另外这俩函数用法都一样,也要设置ddepth 为64位然后取绝对值。注意参数 dx dy 不能同时为1,其他就差不多了。。
o = cv2.imread('p1.jpg',0)
Sobelx = cv2.Sobel(o,cv2.CV_64F,1,0,ksize=3)
Sobely = cv2.Sobel(o,cv2.CV_64F,0,1,ksize=3)
Sobelx = cv2.convertScaleAbs(Sobelx)
Sobely = cv2.convertScaleAbs(Sobely) # 比较一下这两种算子
Sobelxy = cv2.addWeighted(Sobelx,0.5,Sobely,0.5,0)
Scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
Scharry = cv2.Scharr(o,cv2.CV_64F,0,1)
Scharrx = cv2.convertScaleAbs(Scharrx)
Scharry = cv2.convertScaleAbs(Scharry)
Scharrxy = cv2.addWeighted(Scharrx,0.5,Scharry,0.5,0)
cv2.imshow("original",o)
cv2.imshow("Sobelxy",Sobelxy)
cv2.imshow("Scharrxy",Scharrxy)
cv2.waitKey()
cv2.destroyAllWindows()
Sobel 算子的缺点是,当其核结构较小时,精确度不高,而 Scharr 算子具有更高的精度。
Laplacian 算子及其函数应用
拉普拉斯算子是一种二阶导数算子,具有旋转不变性,可以满足不同方向的图像边缘锐化(边缘检测) 的要求。通常其算子的系数之和需要为0.例如:
dst = cv2.Laplacian( src, ddepth[, ksize[, scale[, delta[, borderType]]]] )
- ksize 用于计算二阶导数的核尺寸大小,该值必须是正的奇数
就是比sobel 算子的边缘更亮吧。。。可是换成人脸效果反而没 sobel 好。。
Canny 边缘检测
这个是一种使用多级边缘检测算法检测边缘的方法。
Canny 边缘检测基础
Canny 边缘检测分为如下几个步骤。
步骤 1:去噪。噪声会影响边缘检测的准确性,因此首先要将噪声过滤掉。
步骤 2:计算梯度的幅度与方向。
步骤 3:非极大值抑制,即适当地让边缘“变瘦”。
步骤 4:确定边缘。使用双阈值算法确定最终的边缘信息。
-
应用高斯滤波去除图像噪声
滤波的目的是平滑一些纹理较弱的非边缘区域,以便得到更准确的边缘。高斯滤波器并不是固定的,大小可变,高斯核的大小对于检测边缘的效果有很大的作用,核越大,边缘信息对于噪声的敏感度越低,但是核越大边缘检测的定位错误也会增加,通常 5X5 的核就可以满足大多情况。
dst = cv2.GaussianBlur( src, ksize, sigmaX, sigmaY, borderType )
-
计算梯度
边缘检测算子返回水平方向的Gx和垂直方向的 Gy 和方向?(用角度值表示)
atan2() 表示两个参数的arctan 函数
梯度的方向与边缘的方向是垂直的。通常就近似取值为为水平(左、右)、垂直(上、下)、对角线(右上、左上、左下、右下)等 8 个不同的方向。所以计算梯度时会得到梯度的幅度和角度(代表梯度的方向) 两个值。
幅度和方向,如果幅度较大那就是边缘。
- 非极大值抑制
获得梯度的幅度和方向后,遍历图像中的像素点,判断当前像素点是否是周围像素点中具有相同梯度方向的最大值去除所有非边缘的点,这是边缘细化的过程,针对每一个像素点:
- 如果该点是 正/负 梯度方向上的局部最大值,就保留
- 否则抑制该(归零)
“正/负梯度方向上”是指相反方向的梯度方向,例如黑色的像素点是垂直方向的局部最大值,这些点被处理为边缘点,经过处理对同一方向的若干个边缘点,基本上仅保留一个,实现边缘细化的目的。
- 应用双阈值确定边缘
完成上述步骤后,图像内的强边缘已经在当前获取的边缘图像内,但是一些虚边缘可能也在边缘图像内,这些虚边缘可能是真实图像产生,也可能由于噪声产生,对于后者必须将其剔除。
设置两个阈值,一个高阈值 maxVal 一个低阈值 minVal ,根据当前边缘像素的梯度幅度与这两个阈值之间的关系,判断是否抑制。大于等于 maxVal 就是强边缘,再maxVal 和 minVal 之间为虚边缘(需要保留),如果小于等于 minVal 抑制当前边缘像素。
通过比较获得虚边缘,然后进一步处理,一般通过判断虚边缘与强边缘是否连接,如果与强边缘连接,将该边缘处理为边缘,如果不连接就抑制。
Canny 函数及使用
edges = cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])
- edges 为计算得到的边缘图像
- image 为8位输入图像
- threshold1,2 表示处理过程中的两个阈值
- apertureSize 表示Sobel 算子的孔径大小
- L2gradient 计算图像梯度幅度的标识。默认False,如果为True,则使用更精确的L2 范数进行计算(就是两个方向的导数平方再开方,L1范数就是两个方向导数的绝对值相加)。
o=cv2.imread('p1.jpg',0)
r1=cv2.Canny(o,128,200)
r2=cv2.Canny(o,32,128) # 两个阈值不同,,
cv2.imshow("original",o)
cv2.imshow("result1",r1)
cv2.imshow("result2",r2)
cv2.waitKey()
cv2.destroyAllWindows()
太神奇了吧。。。