如何用ps做网站首页的图片,网站cc攻击用什么来做,皖住房建设厅网站,wordpress文章怎么备份第2章 卷积2.3 二维卷积2.3.1 二维卷积的数学基础与几何直观2.3.1.1 二维卷积的严格数学定义二维卷积的定义#xff1a;
对于两个二维函数 $f(x,y)$ 和 $g(x,y)$#xff0c;它们的卷积定义为#xff1a;对于离散情况#xff0c;如果 $f$ 是 $M \times N$ 的图像#xff0c…第2章 卷积2.3 二维卷积2.3.1 二维卷积的数学基础与几何直观2.3.1.1 二维卷积的严格数学定义二维卷积的定义对于两个二维函数 $f(x,y)$ 和 $g(x,y)$它们的卷积定义为对于离散情况如果 $f$ 是 $M \times N$ 的图像$g$ 是 $K \times L$ 的卷积核卷积的四个步骤翻转Flip将卷积核绕其中心旋转180度滑动Shift将翻转后的卷积核在图像上滑动相乘Multiply将重叠的像素值与卷积核对应值相乘求和Sum将所有乘积结果求和得到输出像素值2.3.1.2 二维卷积的关键参数输出尺寸计算Full模式$O_h I_h K_h - 1$$O_w I_w K_w - 1$Same模式$O_h I_h$$O_w I_w$需要填充Valid模式$O_h I_h - K_h 1$$O_w I_w - K_w 1$填充策略零填充Zero Padding在图像边界外填充0镜像填充Reflect Padding镜像边界像素值重复填充Replicate Padding重复边界像素值环绕填充Wrap Padding将图像视为周期信号2.3.1.3 Python程序二维卷积的深入实现与可视化 第2章 2.3 二维卷积 深入分析二维卷积的数学原理、实现细节和在图像处理中的应用 import numpy as np import matplotlib.pyplot as plt from scipy import signal, ndimage from scipy.fft import fft2, ifft2, fftshift import cv2 import warnings warnings.filterwarnings(ignore) class TwoDimensionalConvolution: 二维卷积的详细讲解与可视化 def __init__(self): # 初始化参数 self.create_sample_images() def create_sample_images(self): 创建示例图像 # 1. 简单测试图像 self.simple_image np.array([ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16] ], dtypefloat) # 2. 创建冲激图像 self.impulse_image np.zeros((7, 7), dtypefloat) self.impulse_image[3, 3] 1.0 # 3. 创建方波图像棋盘格 self.checkerboard np.zeros((8, 8), dtypefloat) for i in range(8): for j in range(8): if (i % 2 0 and j % 2 0) or (i % 2 1 and j % 2 1): self.checkerboard[i, j] 1.0 # 4. 创建更复杂的测试图像 self.complex_image np.zeros((100, 100), dtypefloat) # 添加圆形 center_y, center_x 50, 50 y, x np.ogrid[-center_y:100-center_y, -center_x:100-center_x] mask x**2 y**2 20**2 self.complex_image[mask] 1.0 # 添加矩形 self.complex_image[20:40, 20:40] 0.5 self.complex_image[60:80, 60:80] 0.7 # 添加噪声 noise np.random.randn(100, 100) * 0.1 self.complex_image np.clip(self.complex_image noise, 0, 1) def demonstrate_2d_convolution_basics(self): 演示二维卷积的基本概念 print( * 70) print(2.3.1 二维卷积的基本概念) print( * 70) # 创建简单的图像和卷积核 image self.simple_image kernel np.array([[1, 0, -1], [2, 0, -2], [1, 0, -1]], dtypefloat) # Sobel水平边缘检测 # 手动实现二维卷积 def manual_2d_convolution(image, kernel, modevalid): 手动实现二维卷积 img_h, img_w image.shape kernel_h, kernel_w kernel.shape # 根据模式计算输出尺寸 if mode full: output_h img_h kernel_h - 1 output_w img_w kernel_w - 1 pad_h kernel_h - 1 pad_w kernel_w - 1 elif mode same: output_h img_h output_w img_w pad_h kernel_h // 2 pad_w kernel_w // 2 else: # valid output_h img_h - kernel_h 1 output_w img_w - kernel_w 1 pad_h 0 pad_w 0 # 对图像进行零填充 padded_image np.pad(image, ((pad_h, pad_h), (pad_w, pad_w)), modeconstant) # 翻转卷积核真正的卷积需要翻转 flipped_kernel np.flip(np.flip(kernel, 0), 1) # 初始化输出 output np.zeros((output_h, output_w)) # 执行卷积 for i in range(output_h): for j in range(output_w): # 提取图像块 image_patch padded_image[i:ikernel_h, j:jkernel_w] # 计算点积 output[i, j] np.sum(image_patch * flipped_kernel) return output # 计算卷积结果 conv_full manual_2d_convolution(image, kernel, modefull) conv_same manual_2d_convolution(image, kernel, modesame) conv_valid manual_2d_convolution(image, kernel, modevalid) # 可视化卷积过程 fig, axes plt.subplots(2, 3, figsize(15, 10)) # 1. 原始图像 im1 axes[0, 0].imshow(image, cmapviridis, interpolationnearest) axes[0, 0].set_title(原始图像 (4x4)) axes[0, 0].set_xlabel(X) axes[0, 0].set_ylabel(Y) # 添加像素值标注 for i in range(image.shape[0]): for j in range(image.shape[1]): axes[0, 0].text(j, i, f{image[i, j]:.0f}, hacenter, vacenter, colorwhite) plt.colorbar(im1, axaxes[0, 0]) # 2. 卷积核 im2 axes[0, 1].imshow(kernel, cmapcoolwarm, interpolationnearest) axes[0, 1].set_title(卷积核 (3x3)) axes[0, 1].set_xlabel(Kernel X) axes[0, 1].set_ylabel(Kernel Y) # 添加数值标注 for i in range(kernel.shape[0]): for j in range(kernel.shape[1]): axes[0, 1].text(j, i, f{kernel[i, j]:.0f}, hacenter, vacenter, colorwhite) plt.colorbar(im2, axaxes[0, 1]) # 3. 翻转后的卷积核 flipped_kernel np.flip(np.flip(kernel, 0), 1) im3 axes[0, 2].imshow(flipped_kernel, cmapcoolwarm, interpolationnearest) axes[0, 2].set_title(翻转后的卷积核) axes[0, 2].set_xlabel(Kernel X) axes[0, 2].set_ylabel(Kernel Y) for i in range(flipped_kernel.shape[0]): for j in range(flipped_kernel.shape[1]): axes[0, 2].text(j, i, f{flipped_kernel[i, j]:.0f}, hacenter, vacenter, colorwhite) plt.colorbar(im3, axaxes[0, 2]) # 4. Full模式卷积结果 im4 axes[1, 0].imshow(conv_full, cmapviridis, interpolationnearest) axes[1, 0].set_title(fFull模式: {conv_full.shape[0]}x{conv_full.shape[1]}) axes[1, 0].set_xlabel(输出 X) axes[1, 0].set_ylabel(输出 Y) for i in range(conv_full.shape[0]): for j in range(conv_full.shape[1]): axes[1, 0].text(j, i, f{conv_full[i, j]:.0f}, hacenter, vacenter, colorwhite) plt.colorbar(im4, axaxes[1, 0]) # 5. Same模式卷积结果 im5 axes[1, 1].imshow(conv_same, cmapviridis, interpolationnearest) axes[1, 1].set_title(fSame模式: {conv_same.shape[0]}x{conv_same.shape[1]}) axes[1, 1].set_xlabel(输出 X) axes[1, 1].set_ylabel(输出 Y) for i in range(conv_same.shape[0]): for j in range(conv_same.shape[1]): axes[1, 1].text(j, i, f{conv_same[i, j]:.0f}, hacenter, vacenter, colorwhite) plt.colorbar(im5, axaxes[1, 1]) # 6. Valid模式卷积结果 im6 axes[1, 2].imshow(conv_valid, cmapviridis, interpolationnearest) axes[1, 2].set_title(fValid模式: {conv_valid.shape[0]}x{conv_valid.shape[1]}) axes[1, 2].set_xlabel(输出 X) axes[1, 2].set_ylabel(输出 Y) for i in range(conv_valid.shape[0]): for j in range(conv_valid.shape[1]): axes[1, 2].text(j, i, f{conv_valid[i, j]:.0f}, hacenter, vacenter, colorwhite) plt.colorbar(im6, axaxes[1, 2]) plt.tight_layout() plt.show() # 详细演示卷积计算过程 print(\n二维卷积的详细计算过程:) print(- * 60) # 选取一个具体位置演示计算 print(f图像尺寸: {image.shape}) print(f卷积核尺寸: {kernel.shape}) print(f翻转后的卷积核:\n{flipped_kernel}) # 演示(i1, j1)位置的卷积计算 i, j 1, 1 print(f\n计算输出位置({i}, {j}):) # 提取图像块 image_patch image[i:i3, j:j3] print(f图像块:\n{image_patch}) # 计算点积 result np.sum(image_patch * flipped_kernel) print(f计算结果: {result}) print(\n卷积公式:) print((f * g)(i, j) Σ_m Σ_n f(i-m, j-n) · g(m, n)) print(f对于位置({i}, {j}):) print(f Σ_m Σ_n f({i}-m, {j}-n) · g(m, n)) print(\n计算验证:) actual_value conv_valid[i, j] if i conv_valid.shape[0] and j conv_valid.shape[1] else N/A print(f卷积结果中的值: {actual_value}) print(- * 60) def demonstrate_convolution_with_impulse(self): 演示与二维冲激信号的卷积 print(\n * 70) print(2.3.1 冲激信号) print( * 70) # 创建冲激图像 impulse self.impulse_image # 创建测试图像 test_image self.complex_image[:20, :20] # 使用部分图像 # 创建不同的冲激位置 impulses [] # 1. 中心冲激 impulse_center np.zeros((5, 5), dtypefloat) impulse_center[2, 2] 1.0 # 2. 角落冲激 impulse_corner np.zeros((5, 5), dtypefloat) impulse_corner[0, 0] 1.0 # 3. 多个冲激 impulse_multi np.zeros((5, 5), dtypefloat) impulse_multi[1, 1] 1.0 impulse_multi[3, 3] 1.0 # 4. 线冲激 impulse_line np.zeros((5, 5), dtypefloat) impulse_line[2, :] 1.0 impulses [impulse_center, impulse_corner, impulse_multi, impulse_line] impulse_names [中心冲激, 角落冲激, 多个冲激, 线冲激] # 可视化卷积结果 fig, axes plt.subplots(3, 4, figsize(15, 12)) for idx, (imp, name) in enumerate(zip(impulses, impulse_names)): # 显示冲激图像 ax axes[0, idx] im ax.imshow(imp, cmapgray, interpolationnearest) ax.set_title(f{name}) ax.set_xlabel(X) ax.set_ylabel(Y) # 显示测试图像 ax axes[1, idx] im ax.imshow(test_image, cmapgray, interpolationnearest) ax.set_title(测试图像) ax.set_xlabel(X) ax.set_ylabel(Y) # 计算卷积结果 conv_result signal.convolve2d(test_image, imp, modesame) # 显示卷积结果 ax axes[2, idx] im ax.imshow(conv_result, cmapgray, interpolationnearest) ax.set_title(f卷积结果) ax.set_xlabel(输出 X) ax.set_ylabel(输出 Y) plt.tight_layout() plt.show() # 冲激响应的物理意义 print(\n二维冲激响应的物理意义:) print(- * 60) # 创建系统冲激响应高斯滤波器 def create_gaussian_kernel(size5, sigma1.0): 创建高斯卷积核 kernel np.zeros((size, size)) center size // 2 for i in range(size): for j in range(size): x i - center y j - center kernel[i, j] np.exp(-(x**2 y**2) / (2 * sigma**2)) kernel kernel / np.sum(kernel) # 归一化 return kernel # 创建测试系统模糊系统 gaussian_kernel create_gaussian_kernel(5, 1.5) # 测试不同位置的冲激 test_impulses [] # 中心冲激 center_impulse np.zeros((15, 15)) center_impulse[7, 7] 1.0 # 边缘冲激 edge_impulse np.zeros((15, 15)) edge_impulse[7, 0] 1.0 # 角落冲激 corner_impulse np.zeros((15, 15)) corner_impulse[0, 0] 1.0 test_impulses [center_impulse, edge_impulse, corner_impulse] impulse_desc [中心冲激, 边缘冲激, 角落冲激] fig, axes plt.subplots(3, 3, figsize(15, 12)) for idx, (imp, desc) in enumerate(zip(test_impulses, impulse_desc)): # 显示冲激 ax axes[0, idx] im ax.imshow(imp, cmapgray, interpolationnearest) ax.set_title(f输入: {desc}) ax.set_xlabel(X) ax.set_ylabel(Y) # 显示系统冲激响应 ax axes[1, idx] im ax.imshow(gaussian_kernel, cmapgray, interpolationnearest) ax.set_title(系统冲激响应 (高斯滤波器)) ax.set_xlabel(X) ax.set_ylabel(Y) # 计算系统输出 output signal.convolve2d(imp, gaussian_kernel, modesame) # 显示输出 ax axes[2, idx] im ax.imshow(output, cmapgray, interpolationnearest) ax.set_title(f系统输出) ax.set_xlabel(输出 X) ax.set_ylabel(输出 Y) # 添加轮廓线显示扩散 ax.contour(output, levels5, colorsred, alpha0.5) plt.tight_layout() plt.show() # 冲激响应的数学性质 print(\n二维冲激信号的数学性质:) print(- * 60) # 创建测试图像 test_img np.random.rand(5, 5) print(f测试图像:\n{test_img}) # 创建单位冲激 delta np.zeros((3, 3)) delta[1, 1] 1.0 # 计算卷积 conv_with_delta signal.convolve2d(test_img, delta, modesame) print(f\n与单位冲激卷积结果:\n{conv_with_delta}) # 验证卷积性质 print(\n验证卷积性质:) print(f测试图像与单位冲激卷积应该等于测试图像本身) # 提取有效部分比较 valid_part conv_with_delta[1:4, 1:4] # 去掉边界效应 print(f原始图像中间部分:\n{test_img[1:4, 1:4]}) print(f卷积结果中间部分:\n{valid_part}) error np.max(np.abs(test_img[1:4, 1:4] - valid_part)) print(f最大误差: {error:.10f}) print(f性质验证: {✓ 成立 if error 1e-10 else ✗ 不成立}) # 平移性质验证 print(\n验证平移性质:) # 创建平移冲激 delta_shifted np.zeros((3, 3)) delta_shifted[0, 2] 1.0 # 向右上角平移 conv_shifted signal.convolve2d(test_img, delta_shifted, modesame) print(f与平移冲激卷积结果:\n{conv_shifted}) print(f预期结果应该是测试图像向右上角平移) # 比较 expected_shifted np.zeros_like(test_img) expected_shifted[0:4, 2:5] test_img[1:5, 0:3] # 右上平移 print(f预期平移后图像:\n{expected_shifted}) error_shift np.max(np.abs(conv_shifted[1:4, 1:4] - expected_shifted[1:4, 1:4])) print(f最大误差: {error_shift:.10f}) print(f平移性质验证: {✓ 成立 if error_shift 1e-10 else ✗ 不成立}) print(- * 60) def demonstrate_convolution_with_square_wave(self): 演示与二维方波信号的卷积 print(\n * 70) print(2.3.2 方波信号) print( * 70) # 创建方波图像棋盘格 checkerboard self.checkerboard # 创建不同的方波模式 square_patterns [] # 1. 标准棋盘格 pattern1 checkerboard # 2. 水平条纹 pattern2 np.zeros((8, 8)) pattern2[::2, :] 1.0 # 3. 垂直条纹 pattern3 np.zeros((8, 8)) pattern3[:, ::2] 1.0 # 4. 大方块 pattern4 np.zeros((8, 8)) pattern4[2:6, 2:6] 1.0 square_patterns [pattern1, pattern2, pattern3, pattern4] pattern_names [棋盘格, 水平条纹, 垂直条纹, 大方块] # 可视化不同的方波模式 fig, axes plt.subplots(2, 4, figsize(15, 8)) for idx, (pattern, name) in enumerate(zip(square_patterns, pattern_names)): # 显示方波模式 ax axes[0, idx] im ax.imshow(pattern, cmapgray, interpolationnearest) ax.set_title(f{name}) ax.set_xlabel(X) ax.set_ylabel(Y) # 计算频谱 pattern_fft fft2(pattern) pattern_mag np.abs(fftshift(pattern_fft)) # 显示频谱 ax axes[1, idx] im ax.imshow(np.log1p(pattern_mag), cmaphot, interpolationnearest) ax.set_title(f{name}频谱) ax.set_xlabel(频率 X) ax.set_ylabel(频率 Y) plt.tight_layout() plt.show() # 方波卷积的物理意义 print(\n方波卷积的物理意义:) print(- * 60) # 创建测试图像自然图像模拟 natural_image self.complex_image[:30, :30] # 创建不同的方波卷积核 square_kernels [] # 1. 均值滤波器大方波 mean_kernel np.ones((5, 5)) / 25 # 2. 边缘检测器方向性方波 edge_kernel np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]]) / 3 # 3. 锐化滤波器中心加权的方波 sharpen_kernel np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]]) / 1 # 4. 运动模糊滤波器线状方波 motion_kernel np.zeros((5, 5)) motion_kernel[2, :] 0.2 square_kernels [mean_kernel, edge_kernel, sharpen_kernel, motion_kernel] kernel_names [均值滤波, 边缘检测, 锐化滤波, 运动模糊] fig, axes plt.subplots(4, 4, figsize(15, 15)) for idx, (kernel, name) in enumerate(zip(square_kernels, kernel_names)): # 显示卷积核 ax axes[0, idx] im ax.imshow(kernel, cmapcoolwarm, interpolationnearest) ax.set_title(f{name}卷积核) ax.set_xlabel(X) ax.set_ylabel(Y) # 添加数值标注 for i in range(kernel.shape[0]): for j in range(kernel.shape[1]): ax.text(j, i, f{kernel[i, j]:.2f}, hacenter, vacenter, colorblack, fontsize8) # 显示原始图像 ax axes[1, idx] im ax.imshow(natural_image, cmapgray, interpolationnearest) ax.set_title(原始图像) ax.set_xlabel(X) ax.set_ylabel(Y) # 计算卷积结果 conv_result signal.convolve2d(natural_image, kernel, modesame) # 显示卷积结果 ax axes[2, idx] im ax.imshow(conv_result, cmapgray, interpolationnearest) ax.set_title(f{name}结果) ax.set_xlabel(X) ax.set_ylabel(Y) # 显示频率响应 kernel_padded np.zeros((32, 32)) kh, kw kernel.shape kernel_padded[:kh, :kw] kernel freq_response np.abs(fftshift(fft2(kernel_padded))) ax axes[3, idx] im ax.imshow(np.log1p(freq_response), cmaphot, interpolationnearest) ax.set_title(f{name}频率响应) ax.set_xlabel(频率 X) ax.set_ylabel(频率 Y) plt.tight_layout() plt.show() # 方波卷积的数学性质 print(\n方波卷积的数学性质:) print(- * 60) # 创建测试图像 test_image np.random.rand(5, 5) print(f测试图像:\n{test_image}) # 创建方波卷积核均值滤波器 square_kernel np.ones((3, 3)) / 9 print(f\n方波卷积核 (3x3均值):\n{square_kernel}) # 计算卷积 conv_result signal.convolve2d(test_image, square_kernel, modevalid) print(f\n卷积结果 (Valid模式):\n{conv_result}) # 手动计算验证 print(\n手动验证位置(0,0):) # 提取图像块 image_patch test_image[0:3, 0:3] print(f图像块:\n{image_patch}) # 翻转卷积核 flipped_kernel np.flip(np.flip(square_kernel, 0), 1) print(f翻转后的卷积核:\n{flipped_kernel}) # 计算点积 manual_result np.sum(image_patch * flipped_kernel) print(f手动计算结果: {manual_result}) print(f卷积结果中的值: {conv_result[0, 0]}) error np.abs(manual_result - conv_result[0, 0]) print(f误差: {error:.10f}) # 线性性质验证 print(\n验证线性性质:) # 创建第二个图像 test_image2 np.random.rand(5, 5) # 计算线性组合的卷积 alpha, beta 2.0, 3.0 linear_combination alpha * test_image beta * test_image2 # 分别卷积然后组合 conv1 signal.convolve2d(test_image, square_kernel, modevalid) conv2 signal.convolve2d(test_image2, square_kernel, modevalid) conv_linear alpha * conv1 beta * conv2 # 直接卷积线性组合 conv_direct signal.convolve2d(linear_combination, square_kernel, modevalid) error_linear np.max(np.abs(conv_linear - conv_direct)) print(f线性性质最大误差: {error_linear:.10f}) print(f线性性质验证: {✓ 成立 if error_linear 1e-10 else ✗ 不成立}) # 平移不变性验证 print(\n验证平移不变性:) # 创建平移后的图像 shifted_image np.roll(test_image, shift1, axis0) # 向下平移一行 shifted_image np.roll(shifted_image, shift1, axis1) # 向右平移一列 # 计算平移图像的卷积 conv_shifted signal.convolve2d(shifted_image, square_kernel, modevalid) # 平移卷积结果 conv_original signal.convolve2d(test_image, square_kernel, modevalid) conv_original_shifted np.roll(conv_original, shift1, axis0) conv_original_shifted np.roll(conv_original_shifted, shift1, axis1) # 比较 error_shift np.max(np.abs(conv_shifted - conv_original_shifted)) print(f平移不变性最大误差: {error_shift:.10f}) print(f平移不变性验证: {✓ 成立 if error_shift 1e-10 else ✗ 不成立}) print(- * 60) def demonstrate_image_processing_applications(self): 演示二维卷积在图像处理中的应用 print(\n * 70) print(2.3.3 二维卷积在图像处理中的应用) print( * 70) # 加载或创建测试图像 image self.complex_image # 定义常用的图像处理卷积核 kernels { 均值模糊: np.ones((5, 5)) / 25, 高斯模糊: np.array([[1, 2, 1], [2, 4, 2], [1, 2, 1]]) / 16, 边缘检测(Sobel水平): np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]), 边缘检测(Sobel垂直): np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]]), 拉普拉斯边缘检测: np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]]), 锐化滤波: np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]]), 浮雕效果: np.array([[-2, -1, 0], [-1, 1, 1], [0, 1, 2]]) } # 应用所有卷积核 results {} for name, kernel in kernels.items(): results[name] signal.convolve2d(image, kernel, modesame) # 可视化结果 fig, axes plt.subplots(3, 3, figsize(15, 12)) # 显示原始图像 axes[0, 0].imshow(image, cmapgray) axes[0, 0].set_title(原始图像) axes[0, 0].axis(off) # 显示前8个处理结果 result_items list(results.items())[:8] for idx, (name, result) in enumerate(result_items, 1): ax axes[idx // 3, idx % 3] # 根据处理类型调整显示范围 if 边缘检测 in name or 拉普拉斯 in name or 浮雕 in name: vmin, vmax result.min(), result.max() else: vmin, vmax 0, 1 ax.imshow(result, cmapgray, vminvmin, vmaxvmax) ax.set_title(name) ax.axis(off) plt.tight_layout() plt.show() # 卷积在图像处理中的物理意义 print(\n卷积在图像处理中的物理意义:) print(- * 60) # 创建更复杂的示例 fig, axes plt.subplots(2, 4, figsize(15, 8)) # 1. 噪声去除示例 noisy_image image np.random.randn(*image.shape) * 0.2 noisy_image np.clip(noisy_image, 0, 1) # 应用高斯滤波去噪 denoised signal.convolve2d(noisy_image, kernels[高斯模糊], modesame) axes[0, 0].imshow(noisy_image, cmapgray) axes[0, 0].set_title(带噪声图像) axes[0, 0].axis(off) axes[0, 1].imshow(denoised, cmapgray) axes[0, 1].set_title(高斯滤波去噪) axes[0, 1].axis(off) # 2. 边缘检测和增强 edges_h signal.convolve2d(image, kernels[边缘检测(Sobel水平)], modesame) edges_v signal.convolve2d(image, kernels[边缘检测(Sobel垂直)], modesame) edges np.sqrt(edges_h**2 edges_v**2) # 边缘增强 enhanced image 0.5 * edges enhanced np.clip(enhanced, 0, 1) axes[0, 2].imshow(edges, cmapgray) axes[0, 2].set_title(边缘检测) axes[0, 2].axis(off) axes[0, 3].imshow(enhanced, cmapgray) axes[0, 3].set_title(边缘增强) axes[0, 3].axis(off) # 3. 多尺度分析 # 使用不同尺寸的高斯核 gaussian_sizes [3, 7, 11] for idx, size in enumerate(gaussian_sizes): # 创建高斯核 sigma size / 6 # 经验法则 x np.arange(-size//2, size//2 1) y np.arange(-size//2, size//2 1) X, Y np.meshgrid(x, y) gaussian np.exp(-(X**2 Y**2) / (2 * sigma**2)) gaussian gaussian / np.sum(gaussian) # 应用卷积 blurred signal.convolve2d(image, gaussian, modesame) axes[1, idx].imshow(blurred, cmapgray) axes[1, idx].set_title(f高斯模糊 (size{size})) axes[1, idx].axis(off) # 4. 卷积核可视化 axes[1, 3].axis(off) kernel_info 常用图像处理卷积核: 1. 均值模糊: [[1,1,1], [1,1,1], [1,1,1]]/9 2. 高斯模糊: [[1,2,1], [2,4,2], [1,2,1]]/16 3. Sobel边缘检测: 水平: [[-1,0,1], [-2,0,2], [-1,0,1]] 垂直: [[-1,-2,-1], [0,0,0], [1,2,1]] 4. 拉普拉斯: [[0,1,0], [1,-4,1], [0,1,0]] 5. 锐化: [[0,-1,0], [-1,5,-1], [0,-1,0]] axes[1, 3].text(0.1, 0.5, kernel_info, fontsize9, verticalalignmentcenter, transformaxes[1, 3].transAxes) plt.tight_layout() plt.show() # 卷积与图像特征的数学关系 print(\n卷积与图像特征的数学关系:) print(- * 60) # 创建包含不同特征的测试图像 feature_image np.zeros((50, 50)) # 添加边缘 feature_image[20:30, 20:40] 1.0 # 添加角点 feature_image[10:20, 10:20] 0.7 # 添加纹理 for i in range(5, 45, 10): for j in range(5, 45, 10): feature_image[i:i3, j:j3] 0.5 # 应用不同的卷积核检测不同特征 edge_kernel np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]]) / 8 corner_kernel np.array([[-1, -1, -1], [-1, 1, -1], [-1, -1, -1]]) blob_kernel np.array([[0, 0, 1, 0, 0], [0, 1, 1, 1, 0], [1, 1, 1, 1, 1], [0, 1, 1, 1, 0], [0, 0, 1, 0, 0]]) / 13 # 计算特征响应 edge_response signal.convolve2d(feature_image, edge_kernel, modesame) corner_response signal.convolve2d(feature_image, corner_kernel, modesame) blob_response signal.convolve2d(feature_image, blob_kernel, modesame) # 可视化特征检测 fig, axes plt.subplots(2, 3, figsize(15, 10)) axes[0, 0].imshow(feature_image, cmapgray) axes[0, 0].set_title(测试图像包含边缘、角点、纹理) axes[0, 0].axis(off) axes[0, 1].imshow(edge_response, cmaphot) axes[0, 1].set_title(边缘响应) axes[0, 1].axis(off) axes[0, 2].imshow(corner_response, cmaphot) axes[0, 2].set_title(角点响应) axes[0, 2].axis(off) axes[1, 0].imshow(blob_response, cmaphot) axes[1, 0].set_title(斑点响应) axes[1, 0].axis(off) # 响应直方图 axes[1, 1].hist(edge_response.flatten(), bins50, alpha0.7, label边缘响应) axes[1, 1].hist(corner_response.flatten(), bins50, alpha0.7, label角点响应) axes[1, 1].set_title(响应值分布) axes[1, 1].set_xlabel(响应值) axes[1, 1].set_ylabel(频率) axes[1, 1].legend() axes[1, 1].grid(True, alpha0.3) # 特征检测原理 axes[1, 2].axis(off) feature_info 卷积核与特征检测原理: 1. 边缘检测核: - 设计为对灰度变化敏感 - 在边缘处产生强响应 - 响应值与边缘强度成正比 2. 角点检测核: - 对多个方向的灰度变化敏感 - 在角点处产生强响应 - 响应值与角点尖锐度相关 3. 斑点检测核: - 对局部极值敏感 - 在斑点中心产生强响应 - 响应值与斑点尺寸相关 4. 纹理分析核: - 设计为对特定模式敏感 - 在纹理区域产生特定响应 - 用于纹理分类和分割 axes[1, 2].text(0.1, 0.5, feature_info, fontsize9, verticalalignmentcenter, transformaxes[1, 2].transAxes) plt.tight_layout() plt.show() print(- * 60) def demonstrate_advanced_convolution_topics(self): 演示二维卷积的高级主题 print(\n * 70) print(2.3.4 二维卷积的高级主题) print( * 70) # 1. 可分卷积 print(\n1. 可分卷积 (Separable Convolution):) # 创建一个可分离的卷积核高斯核 def create_separable_gaussian(size5, sigma1.0): 创建可分高斯核 x np.arange(-size//2, size//2 1) gaussian_1d np.exp(-x**2 / (2 * sigma**2)) gaussian_1d gaussian_1d / np.sum(gaussian_1d) # 通过外积创建二维核 gaussian_2d np.outer(gaussian_1d, gaussian_1d) return gaussian_1d, gaussian_2d gaussian_1d, gaussian_2d create_separable_gaussian(5, 1.0) # 测试图像 test_image self.complex_image[:20, :20] # 标准卷积 conv_standard signal.convolve2d(test_image, gaussian_2d, modesame) # 可分卷积先与行核卷积再与列核卷积 intermediate np.zeros_like(test_image) for i in range(test_image.shape[0]): intermediate[i, :] np.convolve(test_image[i, :], gaussian_1d, modesame) conv_separable np.zeros_like(test_image) for j in range(test_image.shape[1]): conv_separable[:, j] np.convolve(intermediate[:, j], gaussian_1d, modesame) # 计算误差 error np.max(np.abs(conv_standard - conv_separable)) # 可视化可分卷积 fig, axes plt.subplots(2, 3, figsize(15, 10)) axes[0, 0].imshow(test_image, cmapgray) axes[0, 0].set_title(测试图像) axes[0, 0].axis(off) axes[0, 1].plot(gaussian_1d, bo-) axes[0, 1].set_title(一维高斯核) axes[0, 1].set_xlabel(位置) axes[0, 1].set_ylabel(权重) axes[0, 1].grid(True, alpha0.3) axes[0, 2].imshow(gaussian_2d, cmaphot) axes[0, 2].set_title(二维高斯核可分离) axes[0, 2].axis(off) axes[1, 0].imshow(conv_standard, cmapgray) axes[1, 0].set_title(标准卷积结果) axes[1, 0].axis(off) axes[1, 1].imshow(conv_separable, cmapgray) axes[1, 1].set_title(可分卷积结果) axes[1, 1].axis(off) axes[1, 2].imshow(np.abs(conv_standard - conv_separable), cmapReds) axes[1, 2].set_title(f绝对误差 (最大{error:.6f})) axes[1, 2].axis(off) plt.tight_layout() plt.show() # 计算复杂度分析 image_size test_image.shape[0] kernel_size gaussian_2d.shape[0] standard_ops image_size**2 * kernel_size**2 separable_ops 2 * image_size**2 * kernel_size print(f标准卷积计算量: O(n²k²) {standard_ops}) print(f可分卷积计算量: O(2n²k) {separable_ops}) print(f加速比: {standard_ops/separable_ops:.2f}倍) # 2. 空洞卷积扩张卷积 print(\n2. 空洞卷积 (Dilated Convolution):) def dilated_convolution(image, kernel, dilation_rate1): 实现空洞卷积 img_h, img_w image.shape kernel_h, kernel_w kernel.shape # 有效核尺寸 effective_h kernel_h (kernel_h - 1) * (dilation_rate - 1) effective_w kernel_w (kernel_w - 1) * (dilation_rate - 1) # 输出尺寸 output_h img_h - effective_h 1 output_w img_w - effective_w 1 output np.zeros((output_h, output_w)) # 翻转卷积核 flipped_kernel np.flip(np.flip(kernel, 0), 1) for i in range(output_h): for j in range(output_w): conv_sum 0 for ki in range(kernel_h): for kj in range(kernel_w): img_i i ki * dilation_rate img_j j kj * dilation_rate if img_i img_h and img_j img_w: conv_sum image[img_i, img_j] * flipped_kernel[ki, kj] output[i, j] conv_sum return output # 创建测试图像和卷积核 test_img_dilated np.random.rand(15, 15) small_kernel np.array([[1, 2, 1], [2, 4, 2], [1, 2, 1]]) / 16 # 应用不同空洞率的卷积 dilation_rates [1, 2, 3] fig, axes plt.subplots(2, 3, figsize(15, 10)) for idx, dilation in enumerate(dilation_rates): # 计算空洞卷积 conv_dilated dilated_convolution(test_img_dilated, small_kernel, dilation) # 显示卷积结果 axes[0, idx].imshow(conv_dilated, cmapviridis) axes[0, idx].set_title(f空洞卷积 (空洞率{dilation})) axes[0, idx].set_xlabel(X) axes[0, idx].set_ylabel(Y) # 显示有效感受野 effective_size 3 (3 - 1) * (dilation - 1) axes[1, idx].text(0.5, 0.5, f有效核尺寸: {effective_size}x{effective_size}\n f输出尺寸: {conv_dilated.shape[0]}x{conv_dilated.shape[1]}, hacenter, vacenter, transformaxes[1, idx].transAxes, fontsize12, bboxdict(boxstyleround,pad0.3, facecolorlightblue)) axes[1, idx].axis(off) plt.tight_layout() plt.show() # 3. 转置卷积反卷积 print(\n3. 转置卷积 (Transposed Convolution):) def transposed_convolution(input_map, kernel, stride1): 实现简单的转置卷积 input_h, input_w input_map.shape kernel_h, kernel_w kernel.shape # 输出尺寸 output_h (input_h - 1) * stride kernel_h output_w (input_w - 1) * stride kernel_w output np.zeros((output_h, output_w)) # 翻转卷积核 flipped_kernel np.flip(np.flip(kernel, 0), 1) for i in range(input_h): for j in range(input_w): # 计算输入值在输出中的位置 out_i i * stride out_j j * stride # 将翻转后的卷积核乘以输入值加到输出对应位置 output[out_i:out_ikernel_h, out_j:out_jkernel_w] input_map[i, j] * flipped_kernel return output # 创建测试输入特征图 feature_map np.array([[1, 0], [0, 1]], dtypefloat) # 创建卷积核 conv_kernel np.array([[1, 2], [3, 4]], dtypefloat) # 应用转置卷积 transposed_output transposed_convolution(feature_map, conv_kernel, stride1) # 可视化转置卷积 fig, axes plt.subplots(1, 3, figsize(12, 4)) axes[0].imshow(feature_map, cmapviridis) axes[0].set_title(输入特征图 (2x2)) axes[0].set_xlabel(X) axes[0].set_ylabel(Y) for i in range(feature_map.shape[0]): for j in range(feature_map.shape[1]): axes[0].text(j, i, f{feature_map[i, j]:.0f}, hacenter, vacenter, colorwhite) axes[1].imshow(conv_kernel, cmapviridis) axes[1].set_title(卷积核 (2x2)) axes[1].set_xlabel(X) axes[1].set_ylabel(Y) for i in range(conv_kernel.shape[0]): for j in range(conv_kernel.shape[1]): axes[1].text(j, i, f{conv_kernel[i, j]:.0f}, hacenter, vacenter, colorwhite) axes[2].imshow(transposed_output, cmapviridis) axes[2].set_title(转置卷积输出 (3x3)) axes[2].set_xlabel(X) axes[2].set_ylabel(Y) for i in range(transposed_output.shape[0]): for j in range(transposed_output.shape[1]): axes[2].text(j, i, f{transposed_output[i, j]:.0f}, hacenter, vacenter, colorwhite) plt.tight_layout() plt.show() # 4. 分组卷积和深度可分离卷积 print(\n4. 分组卷积和深度可分离卷积:) # 模拟多通道图像 multi_channel_image np.random.rand(10, 10, 3) # 3通道图像 # 标准卷积多输入多输出 standard_multi_kernel np.random.rand(3, 3, 3, 4) # 3x3x3输入4个输出通道 # 分组卷积 group_size 3 # 分组数 group_kernels [] for g in range(group_size): group_kernel np.random.rand(3, 3, 1, 4//group_size) # 每组处理1个输入通道 group_kernels.append(group_kernel) # 深度可分离卷积 depthwise_kernel np.random.rand(3, 3, 3, 1) # 深度卷积每个输入通道独立 pointwise_kernel np.random.rand(1, 1, 3, 4) # 逐点卷积1x1卷积 # 计算复杂度比较 input_size 10 input_channels 3 output_channels 4 kernel_size 3 # 标准卷积计算量 standard_complexity input_size**2 * input_channels * output_channels * kernel_size**2 # 深度可分离卷积计算量 depthwise_complexity input_size**2 * input_channels * kernel_size**2 # 深度卷积 pointwise_complexity input_size**2 * input_channels * output_channels * 1**2 # 逐点卷积 separable_complexity depthwise_complexity pointwise_complexity print(f标准卷积计算量: {standard_complexity}) print(f深度可分离卷积计算量: {separable_complexity}) print(f计算量减少比例: {(1 - separable_complexity/standard_complexity)*100:.1f}%) # 可视化卷积类型 fig, axes plt.subplots(2, 2, figsize(10, 8)) convolution_types { 标准卷积: 多个输入通道 → 多个输出通道\n每个输出是输入的加权和, 深度卷积: 每个输入通道独立卷积\n保持通道数不变, 逐点卷积: 1x1卷积\n改变通道数融合信息, 深度可分离卷积: 深度卷积 逐点卷积\n高效的特征提取 } for idx, (title, desc) in enumerate(convolution_types.items()): ax axes[idx // 2, idx % 2] ax.text(0.5, 0.5, f{title}\n\n{desc}, hacenter, vacenter, transformax.transAxes, fontsize11, bboxdict(boxstyleround,pad0.3, facecolorlightblue)) ax.axis(off) plt.tight_layout() plt.show() # 5. 频域卷积 print(\n5. 频域卷积:) # 创建测试图像和卷积核 test_img_fft np.random.rand(32, 32) test_kernel_fft np.random.rand(5, 5) # 时域卷积 conv_time signal.convolve2d(test_img_fft, test_kernel_fft, modesame) # 频域卷积 # 零填充到合适大小 padded_size 64 # 2的幂次便于FFT # 零填充图像和卷积核 img_padded np.zeros((padded_size, padded_size)) kernel_padded np.zeros((padded_size, padded_size)) img_padded[:32, :32] test_img_fft kernel_padded[:5, :5] test_kernel_fft # 傅里叶变换 img_fft fft2(img_padded) kernel_fft fft2(kernel_padded) # 频域相乘 result_fft img_fft * kernel_fft # 逆傅里叶变换 conv_freq np.real(ifft2(result_fft)) # 裁剪到正确大小 conv_freq_cropped conv_freq[:32, :32] # 计算误差 fft_error np.max(np.abs(conv_time - conv_freq_cropped)) # 可视化频域卷积 fig, axes plt.subplots(2, 3, figsize(15, 10)) axes[0, 0].imshow(test_img_fft, cmapviridis) axes[0, 0].set_title(测试图像) axes[0, 0].axis(off) axes[0, 1].imshow(test_kernel_fft, cmapviridis) axes[0, 1].set_title(卷积核) axes[0, 1].axis(off) axes[0, 2].imshow(np.log1p(np.abs(fftshift(img_fft))), cmaphot) axes[0, 2].set_title(图像频谱) axes[0, 2].axis(off) axes[1, 0].imshow(conv_time, cmapviridis) axes[1, 0].set_title(时域卷积结果) axes[1, 0].axis(off) axes[1, 1].imshow(conv_freq_cropped, cmapviridis) axes[1, 1].set_title(频域卷积结果) axes[1, 1].axis(off) axes[1, 2].imshow(np.abs(conv_time - conv_freq_cropped), cmapReds) axes[1, 2].set_title(f绝对误差 (最大{fft_error:.6f})) axes[1, 2].axis(off) plt.tight_layout() plt.show() # 计算复杂度比较 image_size 32 kernel_size 5 # 时域卷积计算量 time_complexity image_size**2 * kernel_size**2 # 频域卷积计算量 fft_size 64 # 填充后大小 fft_complexity 3 * fft_size**2 * np.log2(fft_size) # 3次FFT print(f时域卷积计算量: O(n²k²) ≈ {time_complexity}) print(f频域卷积计算量: O(3N²logN) ≈ {fft_complexity:.0f}) print(f计算量比较: {时域更快 if time_complexity fft_complexity else 频域更快}) print(- * 60) def run_comprehensive_2d_convolution_demo(self): 运行完整的二维卷积演示 print(第2章 2.3节二维卷积 - 全面分析) print( * 70) demonstrations [ self.demonstrate_2d_convolution_basics, self.demonstrate_convolution_with_impulse, self.demonstrate_convolution_with_square_wave, self.demonstrate_image_processing_applications, self.demonstrate_advanced_convolution_topics ] for i, demo in enumerate(demonstrations, 1): print(f\n演示 {i}/{len(demonstrations)}) demo() print(\n * 70) print(二维卷积章节演示完成) print( * 70) # 生成总结 self.generate_2d_convolution_summary() def generate_2d_convolution_summary(self): 生成二维卷积的总结报告 summary 第2章 2.3节二维卷积 - 核心概念总结 一、二维卷积的基本概念 -------------------- 1. 数学定义 离散形式(f * g)(i, j) Σ_m Σ_n f(i-m, j-n) · g(m, n) 连续形式(f * g)(x, y) ∫∫ f(u, v) · g(x-u, y-v) du dv 2. 卷积步骤 - 翻转Flip将卷积核绕中心旋转180度 - 滑动Shift在图像上滑动翻转后的卷积核 - 相乘Multiply对应元素相乘 - 求和Sum所有乘积求和得到输出 3. 卷积模式 - Full模式输出尺寸 输入尺寸 核尺寸 - 1 - Same模式输出尺寸 输入尺寸需要填充 - Valid模式输出尺寸 输入尺寸 - 核尺寸 1 二、二维冲激信号 ---------------- 1. 定义 - 二维冲激δ(x, y) 1 (当x0, y0)其他位置为0 - 离散冲激δ[i, j] 1 (当i0, j0)其他位置为0 2. 性质 - 筛选性质∫∫ f(x, y)δ(x-x₀, y-y₀) dxdy f(x₀, y₀) - 卷积性质f(x, y) * δ(x, y) f(x, y) - 平移性质f(x, y) * δ(x-x₀, y-y₀) f(x-x₀, y-y₀) 3. 应用 - 系统冲激响应测量 - 图像处理滤波器设计 - 特征检测 三、二维方波信号 ---------------- 1. 定义 - 二维方波在矩形区域内有固定值其他区域为0 - 常见形式棋盘格、条纹、方块等 2. 频谱特性 - 包含丰富的频率成分 - 方向性特征明显 - 可用于纹理分析 3. 应用 - 图像特征提取 - 纹理分类 - 模式识别 四、二维卷积在图像处理中的应用 ---------------------------- 1. 图像滤波 - 平滑滤波去除噪声如均值滤波、高斯滤波 - 锐化滤波增强边缘如拉普拉斯滤波、Sobel滤波 - 边缘检测提取轮廓如Canny边缘检测 2. 特征提取 - 边缘特征检测图像边界 - 角点特征检测交点 - 纹理特征分析纹理模式 3. 图像增强 - 对比度增强 - 细节增强 - 去模糊 4. 图像恢复 - 去噪 - 去模糊 - 超分辨率 五、高级卷积技术 ---------------- 1. 可分卷积 - 二维卷积核可分解为两个一维卷积核 - 计算复杂度从O(n²k²)降低到O(2n²k) - 常见可分核高斯核、Sobel核等 2. 空洞卷积 - 在卷积核元素间插入空洞 - 扩大感受野而不增加参数 - 用于多尺度特征提取 3. 转置卷积 - 卷积的逆操作 - 用于上采样和图像生成 - 在生成对抗网络和自编码器中应用 4. 深度可分离卷积 - 深度卷积 逐点卷积 - 大幅减少计算量和参数数量 - 在移动端和嵌入式设备中应用广泛 5. 分组卷积 - 将输入通道分组每组独立卷积 - 减少计算量和参数量 - 提高模型并行性 六、频域卷积 ------------ 1. 卷积定理 - 时域卷积 频域乘积 - F{f * g} F{f} · F{g} 2. 实现方法 - 傅里叶变换图像和卷积核 - 频域相乘 - 逆傅里叶变换得到结果 3. 适用条件 - 大卷积核时效率高 - 需要零填充避免混叠 - 对周期性边界敏感 七、实现优化 ------------ 1. 算法优化 - 根据卷积核大小选择算法 - 小核直接卷积 - 大核FFT卷积 - 可分核可分卷积 2. 内存优化 - 使用原地操作 - 分块处理大图像 - 内存复用 3. 并行优化 - 多线程并行 - GPU加速 - 向量化指令 八、数值稳定性 -------------- 1. 边界处理 - 零填充简单但引入边界效应 - 镜像填充减少边界效应 - 重复填充保持边界连续性 2. 数值精度 - 使用合适的数据类型 - 避免数值溢出 - 控制舍入误差 3. 归一化 - 卷积核归一化保持能量 - 输出范围控制 - 防止数值不稳定 九、实际应用考虑 ---------------- 1. 卷积核设计 - 根据应用需求设计核函数 - 考虑频率响应 - 优化计算效率 2. 参数选择 - 卷积核尺寸 - 卷积核权重 - 步长和填充 3. 性能评估 - 计算复杂度 - 内存占用 - 处理速度 十、发展趋势 ------------ 1. 深度学习中的卷积 - 卷积神经网络 - 可变形卷积 - 动态卷积 2. 硬件加速 - 专用卷积处理器 - FPGA实现 - 神经形态计算 3. 新应用领域 - 医学影像处理 - 遥感图像分析 - 视频处理 二维卷积是图像处理和计算机视觉的基础掌握二维卷积的原理、 实现和应用对于理解现代图像处理技术和深度学习至关重要。 print(summary) # 保存总结到文件 with open(2d_convolution_summary.txt, w, encodingutf-8) as f: f.write(summary) print(总结报告已保存到 2d_convolution_summary.txt) def main(): 主函数 # 创建二维卷积演示对象 conv_2d TwoDimensionalConvolution() # 运行完整的演示 conv_2d.run_comprehensive_2d_convolution_demo() if __name__ __main__: main()2.3 二维卷积总结2.3.1 核心概念回顾二维卷积是图像处理中最核心的数学运算它将一维卷积的概念扩展到二维空间。二维卷积的核心思想可以总结为数学本质加权求和运算描述线性时不变系统对二维输入的响应物理意义模板匹配操作检测图像中的特定模式计算过程翻转、滑动、相乘、求和四个步骤2.3.2 重要性质与定理2.3.2.1 基本性质线性性$f * (\alpha g \beta h) \alpha(fg) \beta(fh)$交换律$f * g g * f$结合律$(fg)h f(gh)$平移不变性$f(x-x_0, y-y_0) * g(x, y) (f*g)(x-x_0, y-y_0)$2.3.2.2 卷积定理二维卷积定理频域卷积定理其中$\mathcal{F}$表示二维傅里叶变换。2.3.2.3 帕塞瓦尔定理2.3.3 实现方法比较实现方法时间复杂度空间复杂度适用场景优点缺点直接卷积O(n²k²)O(1)小卷积核简单直观效率低FFT卷积O(n² log n)O(n²)大卷积核效率高实现复杂可分卷积O(2n²k)O(1)可分离核效率高仅适用可分离核空洞卷积O(n²k²)O(1)扩大感受野不增加参数实现复杂深度可分离卷积O(n²(k² c))O(1)深度网络参数少表达能力有限2.3.4 应用领域总结二维卷积在各个领域都有广泛应用1.图像处理去噪通过平滑滤波去除噪声增强锐化滤波增强细节边缘检测提取图像边界特征提取检测角点、斑点等特征2.计算机视觉特征提取卷积神经网络的基础目标检测滑动窗口检测图像分割区域分割和边界检测立体视觉视差计算3.医学影像病灶检测肿瘤、出血等异常检测组织分割器官、血管等组织分割图像配准多模态图像对齐功能成像血流、代谢等功能分析4.遥感图像处理地物分类土地利用分类变化检测监测环境变化目标识别建筑物、道路等识别图像融合多源数据融合5.视频处理运动检测背景减除、光流计算视频稳定消除摄像机抖动超分辨率提高视频分辨率视频压缩运动估计和补偿2.3.5 设计与实现考虑卷积核设计要点频率响应确保滤波器在所需频带有合适的响应方向选择性根据应用需求设计方向性滤波器尺度适应性多尺度分析需要不同尺寸的卷积核计算效率权衡精度与计算复杂度实现优化策略算法选择根据卷积核大小选择最优算法并行化利用多核CPU或GPU加速内存优化减少内存访问和拷贝数值稳定性防止溢出和精度损失2.3.6 与一维卷积的关系二维卷积是一维卷积在二维空间的扩展概念延伸从时间序列扩展到空间图像数学形式从单重求和扩展到双重求和实现方法许多优化技术可以推广应用差异一维主要用于信号二维主要用于图像2.3.7 学习建议从基础开始先理解一维卷积再学习二维可视化理解通过图像演示理解卷积过程动手实践实现不同的卷积算法实际应用在真实图像处理问题中应用理论学习结合信号处理和图像处理理论2.3.8 前沿发展二维卷积技术仍在不断发展深度学习卷积神经网络的革命性发展可变形卷积自适应感受野形状动态卷积根据输入动态调整卷积核轻量化卷积面向移动设备的优化量子卷积量子计算在图像处理中的应用二维卷积作为图像处理的基础其重要性不仅体现在传统应用中也在现代人工智能和计算机视觉中发挥着关键作用。掌握二维卷积的原理和应用是深入学习计算机视觉、图像处理、深度学习等领域的必备基础。通过本章的学习读者应该能够理解二维卷积的数学定义和物理意义掌握不同卷积模式的实现和区别设计基本的图像处理滤波器在实际图像处理问题中应用卷积技术理解卷积与傅里叶变换的关系这些知识将为学习后续的图像滤波、特征检测、图像分割等更复杂的图像处理技术奠定坚实的基础。第3章 图像滤波3.1 简介想象一下你用手机拍了一张美丽的风景照但照片上有些莫名的彩色斑点可能是CMOS传感器过热或者整体看起来有一层雾蒙蒙的颗粒感可能是高ISO带来的噪点。又或者你想让照片的轮廓更清晰、更突出。这些“去除不需要的东西”和“增强想要的东西”的操作在数字图像处理中很大程度上都属于“图像滤波”的范畴。滤波Filtering顾名思义就是“过滤”。在信号处理领域滤波器用于允许或阻止特定频率的信号通过。图像是一种二维空间信号其“频率”可以直观地理解为灰度的变化快慢。变化剧烈的区域如边缘、纹理对应高频变化平缓的区域如蓝天、墙面对应低频。因此图像滤波的本质是通过一个特定的“窗口”或“模板”称为滤波器核、卷积核在图像上滑动根据窗口内的像素计算出一个新值来替代窗口中心像素的值。这个过程在数学上称为“卷积”。本章我们将系统学习如何通过滤波来“净化”图像去噪和“重塑”图像锐化。首先我们需要认识一下图像中常见的“污染源”——噪声。3.2 图像噪声在图像采集、传输或处理过程中由于传感器材料、环境光照、电子电路干扰等原因引入图像中的随机、不必要的灰度变化称为图像噪声。它是图像滤波的主要“敌人”之一。了解噪声的特性是选择合适滤波器的前提。3.2.1 椒盐噪声核心思想椒盐噪声又称脉冲噪声表现为图像中随机出现的、极其明亮的白点盐和极其黑暗的黑点椒。它通常由图像传感器、传输信道或解码过程中受到突然的强脉冲干扰引起比如镜头上的污点、传输时的瞬时丢包。数学原理椒盐噪声是一种随机噪声其数学模型可以用一个噪声密度p来描述。对于一幅灰度图像I中的任意一个像素点(x, y)其受到椒盐噪声污染后的值I_noisy(x, y)由以下概率决定以概率p/2变为0纯黑胡椒。以概率p/2变为255对于8位图像纯白盐。以概率1-p保持不变。这是一种“全有或全无”的破坏噪声点的值与其原始值、邻域值都无关是孤立的极值点。视觉影响图像上布满黑白斑点严重影响视觉质量和后续处理如边缘检测。3.2.2 高斯噪声核心思想高斯噪声又称正态噪声是自然界中最常见的一种噪声。它源于传感器在低光照条件下的热噪声、放大器噪声等。其特点是噪声值服从高斯分布正态分布意味着它对每个像素点的灰度值增加了一个随机的、微小的、但服从特定统计规律的偏移。数学原理假设原始图像像素值为I(x, y)。添加高斯噪声后的图像I_noisy(x, y)为I_noisy(x, y) I(x, y) N(μ, σ²)其中N(μ, σ²)表示一个均值为μ、方差为σ²的高斯分布随机数。通常μ设为 0表示噪声的平均偏移为0。σ标准差决定了噪声的强度。σ越大噪声越明显。与椒盐噪声不同高斯噪声影响每一个像素且变化是连续的、微小的使得图像看起来像是蒙上了一层细腻的“砂纸”或“雾气”。视觉影响图像整体变得粗糙、模糊细节被淹没在颗粒感中。3.2节完整Python程序总结生成并观察噪声import cv2 import numpy as np import matplotlib.pyplot as plt # 设置中文字体和负号显示 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False def add_salt_pepper_noise(image, prob): 添加椒盐噪声 :param image: 输入图像 (灰度) :param prob: 噪声密度 (每个像素点是噪声点的概率) :return: 加噪后的图像 output np.copy(image) # 生成随机掩码决定哪些像素被污染 # 随机数在 [0, 1) 均匀分布 random_mask np.random.rand(*image.shape) # 以 prob/2 的概率变黑 (0) output[random_mask prob/2] 0 # 以 prob/2 的概率变白 (255) output[random_mask 1 - prob/2] 255 return output def add_gaussian_noise(image, mean0, sigma25): 添加高斯噪声 :param image: 输入图像 (灰度) :param mean: 噪声均值 :param sigma: 噪声标准差 :return: 加噪后的图像 # 生成与图像同形状的高斯噪声矩阵 gauss np.random.normal(mean, sigma, image.shape) # 将噪声加到图像上并确保像素值在 [0, 255] 范围内 noisy image.astype(np.float32) gauss noisy np.clip(noisy, 0, 255).astype(np.uint8) return noisy # 主程序 if __name__ __main__: # 1. 读取图像并转为灰度图 img_original cv2.imread(lena.jpg, cv2.IMREAD_GRAYSCALE) # 请准备一张测试图片如经典的lena图 if img_original is None: # 如果没有图片创建一个简单的渐变图用于演示 print(未找到图像文件创建测试图。) img_original np.zeros((256, 256), dtypenp.uint8) for i in range(256): img_original[:, i] i # 2. 添加椒盐噪声 prob 0.02 # 2%的像素点受影响 img_salt_pepper add_salt_pepper_noise(img_original, prob) # 3. 添加高斯噪声 sigma 30 # 噪声标准差 img_gaussian add_gaussian_noise(img_original, sigmasigma) # 4. 可视化结果 fig, axes plt.subplots(2, 3, figsize(15, 10)) # 显示原图 axes[0, 0].imshow(img_original, cmapgray) axes[0, 0].set_title(原始图像) axes[0, 0].axis(off) # 显示椒盐噪声图 axes[0, 1].imshow(img_salt_pepper, cmapgray) axes[0, 1].set_title(f椒盐噪声 (密度{prob})) axes[0, 1].axis(off) # 显示高斯噪声图 axes[0, 2].imshow(img_gaussian, cmapgray) axes[0, 2].set_title(f高斯噪声 (σ{sigma})) axes[0, 2].axis(off) # 绘制一行像素的剖面图以便更直观地观察噪声 row_to_plot 100 axes[1, 0].plot(img_original[row_to_plot, :], k-, label原始, linewidth1) axes[1, 0].set_title(原始图像第100行灰度剖面) axes[1, 0].set_xlabel(列坐标) axes[1, 0].set_ylabel(灰度值) axes[1, 0].legend() axes[1, 0].grid(True, linestyle--, alpha0.7) axes[1, 1].plot(img_salt_pepper[row_to_plot, :], r-, label椒盐噪声, linewidth1) axes[1, 1].set_title(椒盐噪声第100行灰度剖面) axes[1, 1].set_xlabel(列坐标) axes[1, 1].set_ylabel(灰度值) axes[1, 1].legend() axes[1, 1].grid(True, linestyle--, alpha0.7) axes[1, 2].plot(img_gaussian[row_to_plot, :], b-, label高斯噪声, linewidth1) axes[1, 2].set_title(高斯噪声第100行灰度剖面) axes[1, 2].set_xlabel(列坐标) axes[1, 2].set_ylabel(灰度值) axes[1, 2].legend() axes[1, 2].grid(True, linestyle--, alpha0.7) plt.tight_layout() plt.savefig(noise_comparison.png, dpi300) plt.show() print(程序执行完毕。对比图像已保存为 noise_comparison.png。) print(观察要点) print(1. 椒盐噪声图像中出现孤立的纯黑和纯白点剖面图上表现为垂直的尖峰和低谷。) print(2. 高斯噪声图像整体蒙上一层颗粒感剖面图上原始平滑的曲线变得毛糙、波动。)3.3 均值滤波核心思想最直观的“去噪”想法是什么如果一个像素被噪声干扰了那么看看它周围邻居们的情况用邻居们的“平均意见”来代替它自己的“可能出错”的值。这就是均值滤波也称为线性平均滤波。它是最简单、最易理解的线性空间滤波器。数学原理与算法步骤定义滤波器核模板一个大小为m × n通常为奇数如 3×35×5的矩阵其中所有元素值均为1/(m*n)。例如一个 3×3 的均值滤波核K为K 1/9 * [[1, 1, 1],[1, 1, 1],[1, 1, 1]]卷积操作将该核的中心对准待处理图像的每一个像素(x, y)。核覆盖的区域称为“邻域”。将邻域内每个像素的灰度值与核中对应位置的权重相乘然后求和结果作为输出图像在(x, y)处的新像素值。output(x, y) sum_{i-a}^{a} sum_{j-b}^{b} K(i, j) * I(xi, yj)其中a(m-1)/2,b(n-1)/2。边界处理当核滑动到图像边界时部分核会超出图像范围。常见的处理策略有padding填充用0、镜像或边缘值填充图像外围。valid只计算核完全在图像内的区域输出图像会变小。same常用通过填充使输出图像与输入图像大小相同。频域理解均值滤波是一个低通滤波器。它允许图像中变化缓慢的低频成分如平滑区域通过而抑制变化剧烈的高频成分如噪声、边缘。求平均操作本质上是一种“平滑”或“模糊”。效果与局限优点算法简单计算快对高斯噪声有一定抑制效果。缺点边缘模糊在平滑噪声的同时不可避免地也平滑了真实的图像边缘和细节导致图像整体变模糊。这是因为它对所有邻居“一视同仁”。对椒盐噪声效果差一个极端的黑点或白点被平均到其周围虽然会被减弱但也会污染其周围原本干净的像素形成灰色的“污迹”而不是彻底去除。完整Python程序总结实现与比较均值滤波import cv2 import numpy as np import matplotlib.pyplot as plt from scipy import ndimage # 使用SciPy的卷积函数更高效 def mean_filter_custom(image, kernel_size3): 自定义均值滤波函数 # 创建均值核 kernel np.ones((kernel_size, kernel_size), dtypenp.float32) / (kernel_size * kernel_size) # 使用相关/卷积操作 (这里使用correlate对于对称核与convolve效果相同) # 设置modereflect处理边界使输出大小与输入相同 output ndimage.correlate(image.astype(np.float32), kernel, modereflect) return np.clip(output, 0, 255).astype(np.uint8) # ...后续是主程序加载3.2节生成的带噪图像分别用自定义函数和OpenCV的blur函数进行均值滤波并可视化结果对比对高斯噪声和椒盐噪声的处理效果分析优缺点...