src:源像;ddepth:目标像深度;dx:x方向求导阶数;dy:y方向求导阶数;dst:目标像;ksize:kernel尺寸,说明文档上指出必须是1,3,5,7中的一个,但是实验可以得到应该是小于31的正奇数;如果是-1表示scharr滤波;scale:缩放比例,默认为1;delta:叠加值,默认为0;borderType:边界填充类型;
边缘检测Canny
image:8bit源像,可以是单通道或多通道;threshold迟滞阈值1;threshold迟滞阈值和threshold1没有大小要求,函数内部会调整交换;edges:目标像,二值像;apertureSize:kernel尺寸,默认为3;L2gradient:是否使用L2范式,如果设置为True,计算梯度时使用的是2个方向梯度的平方和开平方,如果设置为False,则使用2个方向梯度的绝对值的和;
第2种接口形式如下:
edges=cv2.Canny(dx, dy, threshold1, threshold2[, edges[, L2gradient]])
canny边沿检测有低错误率、很好地定位边缘点、单一的边缘点响应等优点。canny边沿检测算法由以下几个步骤组成:
第2种接口形式和第1种实现边沿检测的效果是一样的,第2种形式需要先计算像的x和y方向的梯度,所以计算梯度的kernel尺寸在第2种接口中就不需要了。
像梯度反映的是像像素值的变化过程,不管变化大小都考虑在内,所以Sobel,Laplacian变换得到的是一个多级灰度。边沿检测也可以看做是像梯度的一种延伸,不过边沿检测更注意像的“边沿”部分,像梯度变化较小的部分会被忽略,只有较大变化的部分保留下来。
ScharrScharr变换可以看做是使用了Scharr核的Sobel变换,是一种经过改进的Sobel变换,同样也要区分x和y方向分开计算梯度。dst=cvScharrsrc:源像;ddepth:目标像深度;dx:x方向求导阶数;dy:y方向求导阶数;dst:目标像;scale:缩放比例,默认为1;delta:叠加值,默认为0;borderType:边界填充类型;注意Scharr没有ksize参数,因为Scharrkernel的大小固定为3×
先设置dx=1,dy=0计算x方向的梯度,再设置dy=1,dx=0计算y方向的梯度,为了避免出现饱和运算,
dtype设置的是比源图像数据类型CV_8U更高的CV_16S,然后将结果用convertScaleAbs()转换回
CV_8U(np.unit8)类型,最后用addWeighted()将x和y方向的梯度图加权相加。
grad_x = cv2.Scharr(img_src,cv2.CV_16S,1,0)
grad_y = cv2.Scharr(img_src,cv2.CV_16S,0,1)
abs_grad_x = cv2.convertScaleAbs(grad_x)
abs_grad_y = cv2.convertScaleAbs(grad_y)
grad = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
LaplacianLaplacian变换是对像求二阶导数,下是2种3×3尺寸的kernel,这里ksize是Laplacian的入参名称:Laplacian变换不需要区分像的x和y方向计算梯度,从上的2种kernel也可以看到其x和y方向是对称的。在Laplacian变换中,ksize必须是小于31的正奇数,但是当ksize等于1时,这时kernel的尺寸大小并非是其实际尺寸仍然为3×这点从源码上可以看到当ksize=1时,实际为一个包含9个元素的3×3尺寸的kernel:
dst = cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
相同的ksize时,threshold1和threshold2的差值越小,边沿细节越多。
Ksize差异
img_edge3 = cv2.Canny(img_src,20,100,apertureSize=3)
img_edge5 = cv2.Canny(img_src,20,100,apertureSize=5)
img_edge7 = cv2.Canny(img_src,20,100,apertureSize=7)
src:源像;ddepth:目标像深度;dst:目标像;ksize:kernel尺寸,小于31的正奇数;如果为1仍然是一个3×3的kernel;scale:缩放比例,默认为1;delta:叠加值,默认为0;borderType:边界填充类型;Laplacian变换中没有dx或dy参数,因为Laplacian是对像求二阶导数。
相同的threshold值,ksize越大边沿细节越多,这点和Sobel,Scharr,Laplacian计算像梯度效果是一样的。
高斯滤波器平滑输入像;计算梯度幅值像和角度方向;对梯度幅值像应用非最大值抑制;用双阈值处理和连接分析检测和连接边沿。
第一种接口
edges=cv2.Canny(image, threshold1, threshold1[, edges[, apertureSize[, L2gradient]]])
从运行结果可以看到Laplacian中ksize越大,梯度信息越丰富,这点和Sobel变换是一样的。另外在相同的ksize时,二阶Sobel变换和Laplacian变换对比看,Laplacian变换取得的梯度信息要更明显一些。
#Laplacian
grad_lap = cv2.Laplacian(img_src,cv2.CV_16S,ksize=1)
abs_grad_lap1 = cv2.convertScaleAbs(grad_lap)
grad_lap = cv2.Laplacian(img_src,cv2.CV_16S,ksize=3)
abs_grad_lap3 = cv2.convertScaleAbs(grad_lap)
grad_lap = cv2.Laplacian(img_src,cv2.CV_16S,ksize=5)
abs_grad_lap5 = cv2.convertScaleAbs(grad_lap)
#二阶Sobel
grad_x = cv2.Sobel(img_src, cv2.CV_16S, 2, 0, ksize=3)
grad_y = cv2.Sobel(img_src, cv2.CV_16S, 0, 2, ksize=3)
abs_grad_x = cv2.convertScaleAbs(grad_x)
abs_grad_y = cv2.convertScaleAbs(grad_y)
abs_grad_sobel = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
dx:源像的16bitx方向梯度像;dy:源像的16bity方向梯度像;threshold迟滞阈值1;threshold迟滞阈值2;edges:目标像;L2gradient:是否使用L2范式,如果设置为True,计算梯度时使用的是2个方向梯度的平方和开平方,如果设置为False,则使用2个方向梯度的绝对值的和;
文章为作者独立观点,不代表股票配资公司观点