常见的卷积核及其应用
拉普拉斯变换
标准拉普拉斯算子
扩展至对角区域
其中拉普拉斯变换常在图像处理中强调灰度值的突变得到的图层与原图像叠加在一起可以得到锐化的效果。
sobel算子
sobel算子常用边缘检测其中sobel算子分为两种一种为水平方向的一种为垂直方向的。
水平方向:
垂直方向:
高斯算子
使用Python生成高斯模糊核(或称为高斯算子)函数。这个函数会返回一个大小为 (ksize, ksize)
的高斯核,其中 ksize
是核的大小(例如,3表示3x3的核),sigma
是高斯函数的标准差。
import numpy as np
def gaussian_kernel(ksize, sigma):
"""Generate a Gaussian kernel."""
# 初始化高斯核为0
kernel = np.zeros((ksize, ksize))
# 计算高斯核中心
center = ksize // 2
# 填充高斯核
for i in range(ksize):
for j in range(ksize):
diff_x = i - center
diff_y = j - center
kernel[i, j] = np.exp(-(diff_x**2 + diff_y**2) / (2 * sigma**2))
# 归一化高斯核,使其和为1
kernel /= np.sum(kernel)
return kernel
# 示例使用:
ksize = 5
sigma = 1.0
print(gaussian_kernel(ksize, sigma))
运行上述代码,它会返回一个5x5的高斯核。同时可以通过更改 ksize
和 sigma
的值来生成不同大小和模糊程度的高斯核。
应用
import cv2
import numpy as np
import matplotlib.pyplot as plt
def fspecial(mode='average', *params):
"""
生成相应的卷积核模版
:param mode: average 均值滤波器,laplace 拉普拉斯算子,sobel_x 水平方向上的sobel算子,sobel_y 垂直方向上的sobel算子,prewitt prewitt算子,gaussian 高斯核
:param params: 对均值滤波器的大小控制,以及高斯核的控制
:return:
"""
if mode == 'average':
size = params[0] if params else 3
return np.ones((size, size)) / size * size
elif mode == 'laplace':
return np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]])
elif mode == 'sobel-x':
return np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
elif mode == 'sobel-y':
return np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])
elif mode == 'prewitt':
return np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]])
elif mode == 'gaussian':
size = params[0] if params else 3
sigma = params[1] if len(params) > 1 else 0.5
ax = np.arange(-size // 2 + 1., size // 2 + 1.)
xx, yy = np.meshgrid(ax, ax)
kernel = np.exp(-0.5 * (xx ** 2 + yy ** 2) / (sigma ** 2))
return kernel / np.sum(kernel)
else:
raise ValueError("Unsupported filter type")
def imfilter(I, K, is_padding=True, mode=None):
"""
卷积计算
:param I: 原始图像
:param K: 卷积核
:param is_padding: 是否填充
:param mode: 填充模式
:return: 卷积计算结果
"""
k = K.shape[0]
p = k // 2
if is_padding:
if mode is None:
I = np.pad(I, pad_width=p)
else:
I = np.pad(I, pad_width=p, mode=mode)
h, w = I.shape
I_conv = np.zeros((h - k + 1, w - k + 1))
for i in range(p, h - p):
for j in range(p, w - p):
I_conv[i - p, j - p] = sum(sum(I[i - p:i + p + 1, j - p:j + p + 1] * K[0:k, 0:k]))
return tounit8(I_conv)
def tounit8(I_conv):
"""
归一化处理,将图像放缩至[0,255]
:param I_conv: 图像
:return: 图像归一化的结果
"""
return ((I_conv - I_conv.min()) / (I_conv.max() - I_conv.min()) * 255).round()
if __name__ == '__main__':
img = cv2.imread("./img/lenna.jpg", cv2.IMREAD_GRAYSCALE)
K_aver = fspecial("average")
K_lap = fspecial("laplace")
K_sobel = fspecial("sobel-x")
K_gauss = fspecial("gaussian", 5, 5)
K_prewitt = fspecial("prewitt")
img_aver = imfilter(img, K_aver, is_padding=True, mode='edge')
img_lap = imfilter(img, K_lap)
img_sobel = imfilter(img, K_sobel, is_padding=True, mode='reflect')
img_gauss = imfilter(img, K_gauss, is_padding=False)
img_prewitt = imfilter(img, K_prewitt)
fig = plt.figure(figsize=(12, 7))
grid = plt.GridSpec(2, 3)
ax_original = fig.add_subplot(grid[0, 0])
ax_original.imshow(img, cmap='gray')
ax_original.axis('off')
ax_original.set_title("original img")
ax_aver = fig.add_subplot(grid[0, 1])
ax_aver.imshow(img_aver, cmap='gray')
ax_aver.axis('off')
ax_aver.set_title("img after aver")
ax_gauss = fig.add_subplot(grid[0, 2])
ax_gauss.imshow(img_gauss, cmap='gray')
ax_gauss.axis('off')
ax_gauss.set_title('img after gauss')
ax_sobel = fig.add_subplot(grid[1, 0])
ax_sobel.imshow(img_sobel, cmap='gray')
ax_sobel.axis('off')
ax_sobel.set_title('img after sobel-x')
ax_lap = fig.add_subplot(grid[1, 1])
ax_lap.imshow(img_lap, cmap='gray')
ax_lap.axis('off')
ax_lap.set_title('img after lap')
ax_prewitt = fig.add_subplot(grid[1, 2])
ax_prewitt.imshow(img_prewitt, cmap='gray')
ax_prewitt.axis('off')
ax_prewitt.set_title('img after prewitt')
plt.show()