OpenCV-python 高通滤波器

前言

本节将要介绍OpenCV 提供的三种不同的梯度滤波器,或者说高通滤波器:Sobel,Scharr 和 Laplacian。

总的来说:Sobel,Scharr 其实就是求一阶或二阶导数。Scharr 是对 Sobel(使用小的卷积核求解求解梯度角度时)的优化。而Laplacian 是求二阶导数。


一、Sobel算子

其API如下:

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

函数返回其处理结果。

前四个是必须的参数:

    第一个参数是需要处理的图像;
    第二个参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;
    第三、四参数:dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。

其后是可选的参数:

    dst不用解释了;
    ksize是Sobel算子的大小,必须为1、3、5、7。
    scale是缩放导数的比例常数,默认情况下没有伸缩系数;
    delta是一个可选的增量,将会加到最终的dst中,同样,默认情况下没有额外的值加到dst中;
    borderType是判断图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT。

注意:第二个参数在代码中通常使用的却是 cv2.CV_16S,cv2.CV_64F。这是为什么呢?想象一下一个从黑到白的边界的导数是整数,而一个从白到黑的边界点导数却是负数。如果原图像的深度是np.int8 时,所有的负值都会被截断变成 0,换句话说就是把把边界丢失掉。所以如果这两种边界你都想检测到,最好的的办法就是将输出的数据类型设置的更高,比如 cv2.CV_16S,cv2.CV_64F 等。取绝对值然后再把它转回到 cv2.CV_8U。
 

import cv2
import numpy as np
 
filenames = '/longmao.png'
img = cv2.imread(filenames)
cv2.imshow('orginal',img)
#sobel处理
imgx = cv2.Sobel(img,cv2.CV_16S,1,0,ksize=3)
imgy = cv2.Sobel(img,cv2.CV_16S,0,1,ksize=3)
#转回uint8
imgx_uint8 = cv2.convertScaleAbs(imgx)
imgy_uint8 = cv2.convertScaleAbs(imgy)
#x,y方向组合
img = cv2.addWeighted(imgx_uint8,0.5,imgy_uint8,0.5,0)
 
cv2.imshow('sobelimg',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

二、Scharr算子

基本和Sobel算子一样,只是没有了超参数ksize,使用固定的3*3ksize。

#scharr处理
sobelimgx = cv2.Scharr(img,cv2.CV_16S,1,0)
sobelimgy = cv2.Scharr(img,cv2.CV_16S,0,1)

三、Laplacian 算子

图像中的边缘区域,像素值会发生“跳跃”,对这些像素求导,在其一阶导数在边缘位置为极值,这就是Sobel算子使用的原理——极值处就是边缘。如下图:

如果对像素值求二阶导数,会发现边缘处的导数值为0。如下:

Laplace函数实现的方法是先用Sobel 算子计算二阶x和y导数,再求和

#laplace处理
laplace = cv2.Laplacian(img,cv2.CV_16S,ksize=3)
#转回uint8
laplace_img = cv2.convertScaleAbs(laplace)

结果:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章