数字图像处理(二)空间域滤波和频率域滤波

数字图像处理(二)

  • 空间域滤波
    • 平滑空间滤波器(低通)
      • 均值滤波
      • 高斯滤波
      • 双边滤波
      • 中值滤波
    • 锐化空间滤波器(高通)
      • 各向梯度之和算子(拉普拉斯算子(二阶微分))
      • 梯度幅值算子(一阶微分)
      • 梯度幅值改进算子(sobel算子)
    • 混合空间滤波器
  • 频率域滤波
    • 低通滤波
    • 高通滤波
    • 同态滤波

空间域滤波

平滑空间滤波器(低通)

均值滤波

均值滤波器可以一定程度降低高斯噪声,但对椒盐噪声效果不好,并且平滑也会带来图像模糊化。
椒盐噪声是灰度值过大或过小的噪声,对均值的影响较大,所以滤波效果不好。

# 方法1
img_smooth = cv.blur(img_org, ksize=(3, 3))
# 方法2
kernel = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]])/9
img_smooth = cv.filter2D(img_org, -1, kernel)

高斯滤波

高斯滤波构造二维高斯分布的核函数,可以有效的出去图像的高斯噪声。

# 方法1
img_smooth = cv.GaussianBlur(img,(5,5),0.6)
# 方法2
kernel = cv.getGaussianKernel(ksize=3, sigma=0.6) * cv.getGaussianKernel(ksize=3, sigma=0.6).T
img_smooth = cv.filter2D(img_org, -1, kernel)

双边滤波

双边滤波希望在非边缘部分,让图像平滑(高斯滤波); 在边缘部分,让图像变得锐化(让模板中与中心像素差值大的权重更小),可以有效保留边缘。

img_smooth = cv.bilateralFilter(img_org,r,差值,差值)

中值滤波

中值滤波用模板中像素值的中位像素值来确定当前像素值, 可以有效去除椒盐噪声。

11 blur = cv.medianBlur(img_org,5)

锐化空间滤波器(高通)

各向梯度之和算子(拉普拉斯算子(二阶微分))

拉普拉斯算子可以突现出图像中小的细节信息。

kernel0 = np.array([[0, -1, 0],
                   [-1, 4, -1],
                   [0, -1, 0]])
kernel1 = np.array([[-1, -1, -1],
                   [-1, 8, -1],
                   [-1, -1, -1]])
dst = cv.filter2D(img_smooth, -1, kernel0)
img_sharpen = img_org + dst

梯度幅值算子(一阶微分)

kernel0 = np.array([[-1, 0], [0, -1]])
kernel1 = np.array([[0, -1], [-1, 0]])
dst0 = cv.filter2D(img_smooth, -1, kernel0)
dst1 = cv.filter2D(img_smooth, -1, kernel1)
dst = dst0 + dst1
img_sharpen = img_org + dst

梯度幅值改进算子(sobel算子)

sobel算子可以产生较好的边缘检测效果,而且对噪声具有平滑抑制作用,但是得到的边缘较粗,可能出现伪边缘现象。

kernel0 = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])
kernel1 = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
dst0 = cv.filter2D(img_org, -1, kernel0)
dst1 = cv.filter2D(img_org, -1, kernel1)
dst = dst0 + dst1
img_sharpen = img_org + dst

混合空间滤波器

灰度变换平滑锐化等方法组合起来使用

频率域滤波

傅里叶变换可以在全局运算,获取图像的灰度变换情况,并把这种灰度变换情况对应到频率域。通常图像的边缘区域对应频率域的高频部分,平滑区域对应频率域的低频部分。

低通滤波

低通滤波一般实现的是图像平滑,仅保留图像的平滑区域。

def filter(img, d_th, N=1, type='lp', filter='butterworth'):
    '''
	img: 单通道图片
	d_th: 截止频率
	N: butterworth的阶数
	type: lp-低通 hp-高通
	filter:滤波器类型:巴特沃斯、理想、高斯滤波器
    '''
    # 离散快速傅里叶变换
    # dft = cv.dft(np.float32(img), flags=cv.DFT_COMPLEX_OUTPUT)    # 注意这里实部一个通道,虚部一个通道
    dft = np.fft.fft2(img)  # 复数
    dtf_shift = np.fft.fftshift(dft)    # 复数
    rows, cols = img.shape
    mask = np.zeros((rows, cols))  # 生成rows行cols列的二维矩阵
    y_shift, x_shift = np.meshgrid(np.arange(-cols // 2, cols // 2), np.arange(-rows // 2, rows // 2))
    d_uv = np.sqrt(x_shift ** 2 + y_shift ** 2)
    if filter.lower() == 'butterworth':  # 巴特沃斯滤波器
        if type == 'lp':
            mask = 1 / (1 + (d_uv / d_th) ** (2 * N))
        elif type == 'hp':
            mask = 1 / (1 + (d_th / d_uv) ** (2 * N))
        else:
            assert 'type error'
    elif filter.lower() == 'ideal':  # 理想滤波器
        if type == 'lp':
            mask[d_uv <= d_th] = 1
        elif type == 'hp':
            mask[d_uv > d_th] = 1
        else:
            assert 'type error'
    elif filter.lower() == 'gaussian':  # 高斯滤波器
        if type == 'lp':
            mask = np.exp(-(d_uv * d_uv) / (2 * d_th * d_th))
        elif type == 'hp':
            mask = 1 - np.exp(-(d_uv * d_uv) / (2 * d_th * d_th))
        else:
            assert 'type error'
    fshift = dtf_shift * mask
    # 逆傅里叶变换
    f_ishift = np.fft.ifftshift(fshift)
    img_back = np.fft.ifft2(f_ishift)    # 复数
    img_back = np.abs(img_back)    # 实数
    img_back = (img_back - np.amin(img_back)) / (np.amax(img_back) - np.amin(img_back))    # 灰度值:0-1
    img_back = np.uint8(255 * img_back)    # 灰度值:0-255
    return img_back


img_lp = filter(img_org, 30, type="lp", filter="gaussian")

高通滤波

高通滤波一般可以获得图像的边缘,与微分算子类似,与原图像求和,可以锐化图像。

img_hp = filter(img_org, 10, type="hp", filter="gaussian")

同态滤波

同态滤波基本的思想是分离图像的照射分量和反射分量,对照射分量和反射分量进行不同的处理。
一般的同态滤波的步骤主要是:对数变换;傅里叶变换;低频高频分别处理(一般低频抑制,高频增强);逆傅里叶变换;反对数变换。
关于同态滤波的输入灰度级:对有些图像灰度级为[0,255],处理结果会更好;有些图像灰度级为[0,1],处理结果会更好。

def homomorphic_filter(gray_f, d_th=30, rl=0.5, rh=1.5, c=1.0, result_type='abs'):
    # 对数变换:0-255 to 0-1 to 0-0.693
    gray = np.log(gray_f/255.0 + 1.0)
    #gray = np.log(gray_f/1.0 + 1.0)
    
    # 快速傅里叶变换
    gray_fft = np.fft.fft2(gray)
    gray_fftshift = np.fft.fftshift(gray_fft)

    # 创建频率域的坐标矩阵
    rows, cols = gray_f.shape
    y_shift, x_shift = np.meshgrid(np.arange(-cols // 2, cols // 2), np.arange(-rows // 2, rows // 2))  # 注意,//就是除法

    # 计算图像中各个位置的频率值
    d_uv = np.sqrt(x_shift ** 2 + y_shift ** 2)

    # 滤波函数
    mask = (rh - rl) * (1 - np.exp(-c * (d_uv * d_uv) / (d_th * d_th))) + rl
    dst_fftshift = gray_fftshift * mask

    # 傅里叶反变换
    dst_ifftshift = np.fft.ifftshift(dst_fftshift)
    dst_ifft = np.fft.ifft2(dst_ifftshift)

    # 选取复数的幅值
    if result_type == 'abs':
        dst_ifft_amplitude = np.abs(dst_ifft)
    else:
        dst_ifft_amplitude = np.real(dst_ifft)

    # 归一化后再反变换:可有可无。如果dst_ifft_abs.max() < 1, 会让图更暗;如果dst_ifft_abs.max() > 1, 会让图更亮。(不一定对)
    if dst_ifft_amplitude.max() > 1:
        dst_ifft_amplitude = (dst_ifft_amplitude - dst_ifft_amplitude.min()) / (dst_ifft_amplitude.max() - dst_ifft_amplitude.min())
    # 对数反变换:压缩灰度空间(图像会偏暗)
    dst = np.exp(dst_ifft_amplitude)-1
    #dst = dst_ifft_amplitude# 不用对数反变换,图像会亮一些
    dst = (dst - np.min(dst)) / (np.max(dst) - np.min(dst))    # 灰度值:0-1
    dst = np.uint8(255 * dst)    # 灰度值:0-255
    return dst


img_homomorphic = homomorphic_filter(img_org, result_type="abs")

你可能感兴趣的:(计算机视觉,opencv,图像处理)