什么是Gabor滤波器?
Gabor滤波器是一种由正弦波调制的高斯核线性滤波器。Gabor滤波器的频率和方向表示与人类视觉系统相似。Gabor滤波器组通常用于计算机视觉和图像处理。特别适用于边缘检测和纹理分类。一个二维Gabor滤波器是一个由正弦平面波调制的高斯核函数。好处是对光强不敏感,十分适合纹理分析。
Gabor的原理?
公式繁琐不写了,详细可以参考Gabor滤波器
Gabor滤波器怎么应用与纹理分析?
Gabor滤波器提取纹理特征主要包括两个过程:①设计滤波器(例如函数、数目、方向和间隔);②从滤波器的输出结果中提取有效纹理特征集
实际行动中需注意:
1、选择不同方向下的Gabor滤波器
与检测对象趋势相同的方向参数可以使特征点的定位更加准确。
2、选择不同频率下的滤波器
当滤波器纹理与图像作用时,滤波器覆盖下的局部纹理频率与滤波器的频率越接近响应就越大,反之越小。
3、不同的卷积核(kernel size)大小对Gabor滤波核的影响
如果卷积核的边长小于波长,那么整个波形不能包括在卷积核中,使得波形边缘的滤波效果起不到作用。相反,如果如果卷积核的边长大于波长,则不会对滤波器产生什么影响。
4、相位变化对Gabor滤波核的影响
通过相位变化可以改变滤波核中心点的波形,如果滤波核中心点正对波峰(ϕ=0ϕ=0),则会对整张图像起到加强的作用,如果滤波核中心点正对波谷(ϕ=180ϕ=180),则会对整张图像起到减弱的作用。我们应当避免滤波核中心点的波形位于零交叉点,因为这样我们可能会看不到滤波器的任何效果。
5、不同方向不同尺度的Gabor滤波器可以提取对象中的不同特征
实际如何进行特征提取与应用?
以使用skimage.filters.gabor来进行不重复造车。下面的例子是官方给的,展示了如何基于Gabor滤波器组对纹理进行分类。详细可见Gabor filter banks for texture classification。
一般来说,Gabor分为实部和虚部,用实部进行滤波后图像会平滑;虚部滤波后用来检测边缘。本例中Gabor滤波器的频率和方向表示选择与人类视觉系统相似的。利用各种不同的Gabor滤波核的 实部 对图像进行滤波。然后将 滤波后 图像的 均值和方差 作为分类特征,为简单起见,该特征基于最小平方误差。
在进行实例前,先学习两个函数:
1、skimage.filters.gabor(image, frequency, theta=0, bandwidth=1, sigma_x=None, sigma_y=None, n_stds=3, offset=0, mode='reflect', cval=0)
用途: 将Gabor滤波核的实部和虚部应用于图像,并将响应作为一对数组返回。
参数:
image:2-D array
输入图像(2维)
frequency:float
谐波函数的空间频率. Specified in pixels.
theta:float, optional
方向以弧度制。如果是0,谐波在x方向上。
bandwidth:float, optional
滤波器捕获的带宽。在带宽固定的情况下,sigma_x和sigma_y会随着频率的增加而减小。如果sigma_x和sigma_y由用户设置,则忽略此值。
sigma_x, sigma_y:float, optional
x和y方向上的标准差。这些方向适用于旋转前的核。如果 t h e t a = 1 / 2 ∗ p i theta= 1/2*pi theta=1/2∗pi,那么核旋转90度,sigma_x控制垂直方向。
n_stds:scalar, optional
内核的线性大小是n_stds(默认为3)标准差。
offset:float, optional
谐波函数的相位偏移以弧度制。
mode:{‘constant’, ‘nearest’, ‘reflect’, ‘mirror’, ‘wrap’}, optional
用于图像与内核卷积的模式,传递给ndi.convolve
cval:scalar, optional
如果卷积模式是“constant”常数,则指定该常数值。该参数被传递给ndi.convolve。
2、skimage.filters.gabor_kernel(frequency, theta=0, bandwidth=1, sigma_x=None, sigma_y=None, n_stds=3, offset=0, dtype=
用途: 返回复杂的2D-Gabor过滤器内核。
Gabor核是由复杂的谐波函数调制的高斯核。谐波函数由虚正弦函数和实余弦函数组成。空间频率与谐波的波长和高斯核的标准差成反比。带宽也与标准差成反比。
参数:
frequency:float
谐波函数的空间频率。
theta:float, optional
方向以弧度制。如果是0,谐波在x方向上。
bandwidth:float, optional
滤波器捕获的带宽。在带宽固定的情况下,sigma_x和sigma_y会随着频率的增加而减小。如果sigma_x和sigma_y由用户设置,则忽略此值。
sigma_x, sigma_y:float, optional
滤波器捕获的带宽。在带宽固定的情况下,sigma_x和sigma_y会随着频率的增加而减小。如果sigma_x和sigma_y由用户设置,则忽略此值。
n_stds:scalar, optional
内核的线性大小是n_stds(默认为3)标准差
offset:float, optional
谐波函数的相位偏移以弧度制。
dtype{np.complex64, np.complex128}
指定过滤器是单精度复数还是双精度复数。
import matplotlib.pyplot as plt
import numpy as np
from scipy import ndimage as ndi
from skimage import data#引入数据
from skimage.util import img_as_float
from skimage.filters import gabor_kernel#引入Gabor核
# 准备滤波器的核,这里采用了16个核
kernels = []
for theta in range(4):
theta = theta / 4. * np.pi#核的方向(0,45,90,135)
for sigma in (1, 3):
for frequency in (0.05, 0.25):
kernel = np.real(gabor_kernel(frequency, theta=theta,
sigma_x=sigma, sigma_y=sigma))
kernels.append(kernel)
#这样就建立了16个kernel.theta4*sigma2*frequency2=16种组合情况
shrink = (slice(0, None, 3), slice(0, None, 3))
brick = img_as_float(data.brick())[shrink]#提取到砖材质图像
grass = img_as_float(data.grass())[shrink]#提取到草材质图像
gravel = img_as_float(data.gravel())[shrink]#提取到砂石材质图像
image_names = ('brick', 'grass', 'gravel')
images = (brick, grass, gravel)
def compute_feats(image, kernels):#计算特征函数
feats = np.zeros((len(kernels), 2), dtype=np.double)#选择在过滤后以均值和方差作为特征,所以有两个
for k, kernel in enumerate(kernels):
filtered = ndi.convolve(image, kernel, mode='wrap')#将图像和Gabor核进行卷积
feats[k, 0] = filtered.mean()#将过滤后的进行平均值
feats[k, 1] = filtered.var()#进行方差
return feats
#准备参考特性
ref_feats = np.zeros((3, len(kernels), 2), dtype=np.double)#3种材质,16个核,2种特征表示
ref_feats[0, :, :] = compute_feats(brick, kernels)
ref_feats[1, :, :] = compute_feats(grass, kernels)
ref_feats[2, :, :] = compute_feats(gravel, kernels)
def match(feats, ref_feats):#匹配函数,用于计算最小平方误差
min_error = np.inf
min_i = None
for i in range(ref_feats.shape[0]):
error = np.sum((feats - ref_feats[i, :])**2)
if error < min_error:
min_error = error
min_i = i
return min_i
print('Rotated images matched against references using Gabor filter banks:')
print('original: brick, rotated: 30deg, match result: ', end='')
feats = compute_feats(ndi.rotate(brick, angle=190, reshape=False), kernels)
print(image_names[match(feats, ref_feats)])
print('original: brick, rotated: 70deg, match result: ', end='')
feats = compute_feats(ndi.rotate(brick, angle=70, reshape=False), kernels)
print(image_names[match(feats, ref_feats)])
print('original: grass, rotated: 145deg, match result: ', end='')
feats = compute_feats(ndi.rotate(grass, angle=145, reshape=False), kernels)
print(image_names[match(feats, ref_feats)])
#计算规范化以后的对应核的power图
def power(image, kernel):
#对图像进行规范化,以便更好地进行比较
image = (image - image.mean()) / image.std()
return np.sqrt(ndi.convolve(image, np.real(kernel), mode='wrap')**2 +
ndi.convolve(image, np.imag(kernel), mode='wrap')**2)
# 绘制筛选滤波器组核及其响应的图。
results = []
kernel_params = []
for theta in (0, 1):
theta = theta / 4. * np.pi
for frequency in (0.1, 0.4):
kernel = gabor_kernel(frequency, theta=theta)
params = 'theta=%d,\nfrequency=%.2f' % (theta * 180 / np.pi, frequency)#核的标题
kernel_params.append(params)
# 保存每个图像的kernel和power图像
results.append((kernel, [power(img, kernel) for img in images]))
#设定各个子图像的位置
fig, axes = plt.subplots(nrows=5, ncols=4, figsize=(5, 6))
plt.gray()
fig.suptitle('Image responses for Gabor filter kernels', fontsize=12)
axes[0][0].axis('off')
# 绘制原始图像
for label, img, ax in zip(image_names, images, axes[0][1:]):
ax.imshow(img)
ax.set_title(label, fontsize=9)
ax.axis('off')
for label, (kernel, powers), ax_row in zip(kernel_params, results, axes[1:]):
# 绘制Gabor核
ax = ax_row[0]
ax.imshow(np.real(kernel))
ax.set_ylabel(label, fontsize=7)
ax.set_xticks([])
ax.set_yticks([])
# 绘制Gabor响应,每个滤波器使用对比度归一化
vmin = np.min(powers)
vmax = np.max(powers)
for patch, ax in zip(powers, ax_row[1:]):
ax.imshow(patch, vmin=vmin, vmax=vmax)
ax.axis('off')
结果如下图所示:可以看到不同的滤波器设定,得到的特征相应完全不同。所以对于具体的问题应该具体分析应该采用怎么样的滤波器参数。