ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

OpenCV频率域滤波实战:高斯、理想、巴特沃斯消除周期噪声

OpenCV频率域滤波实战:高斯、理想、巴特沃斯消除周期噪声 简介频率域滤波是图像处理中的经典方法通过傅里叶变换将图像分解为低频与高频分量再对频域谱进行修改从而完成平滑、去噪等操作。一份基于OpenCV的示例工程面向图像处理初学者和OpenCV使用者以高斯、理想、巴特沃斯三种低通滤波器为主线展示从离散傅里叶变换、滤波核构造、频谱修改到逆变换与归一化的完整过程。包内共8个文件一个cpp源文件为核心代码附有dsp、dsw、ncb、plg、opt等Visual C工程文件可快速用VC编译运行两幅bmp测试图像方便观察滤波前后的效果整个压缩包仅86KB非常轻量。代码中对三种滤波器的截止频率和过渡特性做了差异化处理便于对比高斯滤波的平滑效果、理想滤波器陡峭截断可能引发的振铃现象以及巴特沃斯滤波器的平坦过渡带表现。通过该示例读者能直观理解频率域滤波与空间域滤波的关系掌握OpenCV中DFT相关函数用法已有2149人学习下载适合作为频域低通滤波教学演示、图像去噪实验或OpenCV二次开发的参考。1. 频率域滤波不是炫技OpenCV 里高斯、理想、巴特沃斯到底解决什么问题在工业视觉里我常被问频率域滤波能做的cv2.GaussianBlur 十行就做完了何必折腾这个问题成立直到你碰见摩尔纹、周期性噪点、玻璃划痕这些“有规律”的噪声——空间域里你要为它们手工设计一个几十像素宽的卷积核而频率域里只需要在频谱图上找到对应亮点用高斯、理想、巴特沃斯三种滤波器之一把那个频率“摘掉”。这份用 OpenCV 实现的频率域滤波方案核心链路只有三步cv2.dft 把图像送到频域按传递函数整形频谱cv2.idft 逆变换回来。它适合做图像平滑、去周期噪声、细节增强依赖只有 opencv-python 和 numpy新手照着步骤能跑通熟手可以直接抄参数和避坑经验。2. 用 cv2.dft 把图像送进频域从灰度图到居中频谱的完整数据流2.1 为什么一定要 fftshift低频不在中心滤波器就没法设计OpenCV 的 cv2.dft 做完正变换后低频分量直流 DC默认放在矩阵的四个角上而不是中心。这不是 bug而是 DFT 数学定义里零频在第一个样本位置的直接结果。于是你会看到一张“四个角各有一团亮斑”的频谱图低频在角落、高频在中间这和我们脑子里“中心是低频、往外是高频”的直觉完全相反。工程上做频率域滤波时几乎所有滤波器都以“中心为圆心、D0 为半径”来构造比如理想低通的圆形区域、高斯低通的指数衰减。如果你不先把频谱中心化滤波器的圆心就得挪到四个角上一个完整圆盘被切成四块分布在角落边界处的处理会非常别扭代码也难读。所以标准做法是补一步 np.fft.fftshift。这里有个容易搜错的关键点中心化函数是 numpy 的不是 cv2 的。OpenCV 本身没有提供 fftshift/ifftshift 接口网上很多教程直接写 np.fft.fftshift(dft)你搜“opencv fftshift”反而找不到结果。它做的事情很简单把矩阵的前半行和后半行互换再把前几列和后几列互换纯粹是数据重排不改变任何数学值。对偶数尺寸图像fftshift 后中心和几何中心完全重合对奇数尺寸图像中心点会偏移不到一个像素实际构造滤波器时用 rows//2 和 cols//2 来定位即可肉眼和绝大多数应用都察觉不到这零点几个像素的偏差。整套流程里 shift 是出现频率最高的翻车点后面避坑章节还会专门讲。2.2 最小数据流从灰度图到居中频谱代码与参数说明先装好依赖pip install opencv-python numpy。下面的代码把一张灰度图读进来转 float32做 DFT再把频谱中心化并输出一张可视化用的幅值谱。import cv2 import numpy as np # 1. 灰度图 转 float32cv2.dft 只接受浮点输入 img cv2.imread(board_gray.png, cv2.IMREAD_GRAYSCALE) img_f img.astype(np.float32) # 2. 填充到“DFT 友好尺寸”提高计算效率也降低周期延拓的突变程度 rows, cols img_f.shape nrows cv2.getOptimalDFTSize(rows) # 返回包含 2、3、5 因子的高效尺寸 ncols cv2.getOptimalDFTSize(cols) img_pad np.zeros((nrows, ncols), np.float32) img_pad[:rows, :cols] img_f # 3. 正变换 频谱居中 dft cv2.dft(img_pad, flagscv2.DFT_COMPLEX_OUTPUT) dft_shift np.fft.fftshift(dft) # 4. 幅值谱可视化注意这只是用来“看”的不要拿它做滤波 mag cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]) mag_log np.log(1.0 mag) # 压缩超大动态范围 mag_vis cv2.normalize(mag_log, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8) cv2.imwrite(spectrum.png, mag_vis)第三步的 cv2.dft 输出的不是单通道矩阵而是双通道——第 0 通道是实部第 1 通道是虚部。这是复数频谱的存储方式后面做滤波时也要记住这个布局。flagscv2.DFT_COMPLEX_OUTPUT 就是告诉 OpenCV 按复数格式输出如果不传这个 flag默认行为在不同版本里会有差异建议总是显式写上。第二步先做 padding主要为了性能cv2.getOptimalDFTSize 返回的尺寸对 FFT 算法更友好通常由小质数因子组成。另一个更实际的原因是DFT 假设图像是无限周期延拓的图像边界在延拓时会出现强度跳变频谱里会多出一条与边界垂直的亮线padding 能稍微缓解这种边界泄漏。padding 区域本身是黑边后续滤波完成后需要裁剪掉否则恢复图四周会有一圈黑框。第四步的 log(1mag) 是频谱可视化的标准操作原始频谱里中心直流分量的值可能是四周高频分量的几万倍直接显示只有中心一个白点取对数后才能看到从中心向外辐射的纹理结构。注意可视化时取对数没问题但如果把取过对数的频谱拿去做滤波再 idft结果会完全错乱——对数是非线性变换只用于显示。提示如果只是验证流程不追求速度可以跳过 getOptimalDFTSize直接在原始尺寸上做 dft。滤波器尺寸跟着原始尺寸走代码更简单但频谱边缘的泄漏会比 padding 后明显一些。2.3 频谱亮斑和空间周期的对应关系判断 D0 用的直觉做频率域滤波最值钱的能力不是写代码而是“看懂频谱图”。周期为 T 像素的条纹在频谱上会产生一对对称亮斑这对亮斑到中心的距离大约是 N / T其中 N 是图像宽度。反过来你看到频谱上在距离中心 16 像素处有一对亮点说明原图里存在周期约 16 像素的重复纹理。这个换算关系直接决定滤波器的 D0 取值。比如图像是 256 像素宽有一组周期 16 像素的摩尔纹那频谱亮斑离中心约 16 个像素低通滤波器只要把 D0 设在 8~10就能把这对亮点压掉同时保留更靠近中心的真实图像能量。D0 的单位是“像素”但它衡量的是频率样本的距离不是什么抽象比例。另外对实数图像做 DFT频谱是共轭对称的——亮点总是成对出现且关于中心对称。这一点可以作为自检工具如果你的频谱图出现了一个孤零零的亮点多半是数据读取出了问题比如把复数频谱当成单通道图像显示或者 padding 时把图像放歪了。3. 构造三种低通传递函数理想、高斯、巴特沃斯的公式与 D0、n 参数3.1 理想低通滤波器一行 np.where但它带来的振铃最凶理想低通的传递函数是硬截断距离中心小于等于 D0 的频点全部保留大于 D0 的频点全部置零。用代码表达就是一句话def ideal_lp(shape, D0): rows, cols shape y, x np.mgrid[0:rows, 0:cols] D np.sqrt((x - cols // 2) ** 2 (y - rows // 2) ** 2) return np.where(D D0, 1.0, 0.0).astype(np.float32)np.mgrid 生成坐标网格后D 就是每个频点到中心的欧氏距离。np.where 把距离小于 D0 的位置填 1、其余填 0得到一张 0/1 二值圆盘。这里有个隐藏前提滤波器尺寸应当与 padding 后的频谱尺寸一致也就是调用时传入 (nrows, ncols)而不是原始图像尺寸。理想低通在数学上很漂亮工程上却几乎是“只可演示、不可交付”的典型。原因是频域的矩形窗逆变换到空间域对应的是 sinc 函数它带有明显的正负旁瓣。用这张二值圆盘去过滤频谱相当于让图像和 sinc 核做卷积结果就是图像边缘处出现一圈一圈明暗相间的光晕专业说法叫吉布斯振铃。D0 越小、截断越狠振铃越明显。如果非得用理想滤波器做效果对比我的习惯是只在演示“频率域能做什么”的时候用真正要落地去噪或锐化时一律换高斯或低阶巴特沃斯。振铃不是参数没调好而是滤波器形状的固有属性换 D0 只能换振铃位置不能消除。3.2 高斯低通平滑过渡、没有振铃参数只有一个 D0高斯低通的传递函数是 H(u,v) exp(-D² / (2 * D0²))。它的特点是频谱里没有“一刀切”的边界所有频点都按距离指数衰减所以不会产生 sinc 旁瓣振铃基本为零。这也是工业场景默认首选它的原因。def gaussian_lp(shape, D0): rows, cols shape y, x np.mgrid[0:rows, 0:cols] D np.sqrt((x - cols // 2) ** 2 (y - rows // 2) ** 2) return np.exp(-(D * D) / (2 * D0 * D0)).astype(np.float32)注意代码里写的是 D * D这是距离的平方对应公式里的 D²。很多第一次写高斯滤波器的人会漏掉平方把衰减写成了 exp(-D / (2D0²))结果是高频衰减为线性、低频也被过度压掉平滑效果变得很怪。另一个常见问题是 D 和 D0 的单位混用D 是像素距离D0 也必须用像素不要拿空间域的 sigma 直接填进来。高斯低通滤波器在数学上和空间域高斯模糊有对偶关系高斯函数的傅里叶变换仍是高斯函数。所以空间域里 cv2.GaussianBlur 做的事情本质上就是在频域乘了一个高斯形状的低通滤波器。差别主要在边界处理——OpenCV 空间域卷积默认做反射填充而频率域是周期延拓所以同一个参数下两种实现的结果不会像素级一致但肉眼看差别很小。实际项目里选一条路走通就好不必来回换算 sigma 和 D0。D0 的调试起点我一般取图像短边的 1/20 到 1/10。比如 1024x1024 的图D0 从 50 开始试效果不够平滑就加大平滑过头丢细节就减小。这个范围比固定取 30、50 这种“魔法数字”收敛快得多。3.3 巴特沃斯低通用阶数 n 控制过渡带的陡峭度振铃和保留细节的旋钮巴特沃斯低通的传递函数是 H 1 / (1 (D / D0)^(2n))。它介于理想和高斯之间n 小的时候曲线平缓接近高斯n 大的时候过渡带变陡逼近理想低通。工程价值在于你可以通过 n 精确控制“滤波器的锐度”。def butterworth_lp(shape, D0, n2): rows, cols shape y, x np.mgrid[0:rows, 0:cols] D np.sqrt((x - cols // 2) ** 2 (y - rows // 2) ** 2) return (1.0 / (1.0 (D / D0) ** (2 * n))).astype(np.float32)n 取 1 时这个公式就是一阶系统最常见的响应形态幅频曲线和 RC 低通滤波器是同一种形状衰减非常平缓n 取 2 时过渡带变陡一些振铃还不太明显是我最常用的起点n 到 4 以上行为已经接近理想低通振铃随之明显基本失去了用巴特沃斯的理由。所以参数组合一般固定为D0 决定截止位置n 决定过渡带陡峭程度先在 n2 上把 D0 调好再考虑要不要动 n。巴特沃斯代码里有个容易被忽略的点D0 时(0/D0)^(2n)0分母是 1所以直流分量增益为 1这是正确的低通行为。如果 D0 传 0 会导致除零因此 D0 至少要给 1 以上。和理想低通相比巴特沃斯的优势是“留有余地”在 D0 之外的频点不是立刻归零而是逐渐衰减过渡带里的能量仍然部分保留。这对真实图像很重要因为图像细节和噪声通常不会严格分居两个半径之外平滑的过渡带能减少细节的突然丢失。3.4 一张表选型三种滤波器的行为差异和推荐参数滤波器传递函数过渡带振铃表现推荐参数理想低通D D0 取 1否则 0最陡硬截断边缘有明显光晕严重仅用于效果演示高斯低通exp(-D²/2D0²)平滑无旁瓣基本无振铃D0 图像短边/20 ~ /10巴特沃斯低通1 / (1 (D/D0)^(2n))由 n 控制陡峭度n4 时明显n2 轻微D0 同上n2 起步补充一个实用细节上面三个滤波器都以“到中心的距离”为变量所以天然各向同性。如果你要保留水平方向的纹理、只滤垂直方向需要把 D 从欧氏距离换成椭圆距离比如 D sqrt((dx * scale_x)² (dy * scale_y)²)。这个扩展在工业瑕疵检测里很常见但先要把圆形版本跑通再改。4. 从滤波到恢复复数乘法、idft 逆变换与结果验证的完整流程4.1 让滤波器和频谱对齐尺寸一致、通道扩展、乘法方式滤波器 H 是单通道二维矩阵而 dft_shift 是双通道复数矩阵。直接拿 H 去乘 dft_shift 会报维度不一致。常见的处理方式是把 H 在最后一个维度上复制成两通道让实部和虚部乘同一个增益H gaussian_lp((nrows, ncols), D040) # H 是 (nrows, ncols) 单通道频谱是 (nrows, ncols, 2) 双通道 H2 np.stack([H, H], axis-1) # 变成 (nrows, ncols, 2) filtered_shift dft_shift * H2 # 实部、虚部分别乘同一个滤波器系数这段乘法是逐元素进行的复数乘法的规则是实部乘实部、虚部乘虚部滤波器系数是实数所以不存在交叉项。H2 的两个通道数值一样这是“实数滤波器作用于复数频谱”的标准姿势。也可以用 cv2.mulSpectrums(dft_shift, H2, 0) 达到同样效果它内部做了复数乘法优化但要求两个输入都是双通道且类型一致反而多一层约束。我的经验是直接 numpy 乘法更直观出问题时也好排查。真正要检查的只有两件事H.shape 是否等于 dft_shift.shape[:2]H 的数据类型是否和频谱一致频谱是 float32H 也要先转 float32。如果这里出现形状对不上最常见的原因是滤波器用了原始图像尺寸、频谱用了 padding 后尺寸。写代码时我习惯把 shape 直接传进滤波器构造函数而不是在函数内部读取 image.shape。4.2 逆变换、裁剪与归一化把复数频谱还原成能看的图像滤波做完后逆变换的顺序和正变换正好相反先 ifftshift 把低频从中心挪回四角再做 cv2.idft取实部裁掉 padding最后归一化到 0~255。下面是一个可以直接复制的完整函数import cv2 import numpy as np def frequency_filter(img, H): # img: 单通道灰度图 (uint8 或 float32) # H: 与 padding 后频谱同尺寸的 float32 滤波器 img_f img.astype(np.float32) rows, cols img_f.shape nrows cv2.getOptimalDFTSize(rows) ncols cv2.getOptimalDFTSize(cols) img_pad np.zeros((nrows, ncols), np.float32) img_pad[:rows, :cols] img_f if H.shape ! (nrows, ncols): raise ValueError(滤波器尺寸 %s 与填充后频谱尺寸 %s 不一致 % (H.shape, (nrows, ncols))) dft cv2.dft(img_pad, flagscv2.DFT_COMPLEX_OUTPUT) dft_shift np.fft.fftshift(dft) H2 np.stack([H, H], axis-1) filtered_shift dft_shift * H2 filtered np.fft.ifftshift(filtered_shift) # 关键把低频移回四角 img_back cv2.idft(filtered)[:, :, 0] # 取实部通道 result img_back[:rows, :cols] # 裁掉 padding 黑边 result cv2.normalize(result, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8) return resultnp.fft.ifftshift 这一步很多人会漏掉。fftshift 把低频移到中心滤波操作在中心坐标系里完成逆变换前必须再用 ifftshift 把低频搬回四角。如果少这一步idft 的结果会把频谱的四个象限错位拼接图像看起来像被切成了四块重新摆放亮度还可能出现反转。cv2.idft 返回的同样是双通道复数格式[ :, :, 0] 取实部虚部理论上接近 0。DFT 本身没有归一化正变换乘了 N 倍的缩放会留在 idft 结果里所以恢复图的像素值范围通常是原始值的几倍大必须 normalize 到 0~255。也可以给 cv2.idft 传 flagscv2.DFT_SCALE让它内部除以 N但我更习惯先裁剪再手动 normalize这样可选范围和控制点都更清楚。注意调这个函数时先用 H 全为 1 的滤波器跑一遍结果应该和原图几乎一致。如果这一步都不对问题一定出在 shift 或 padding和滤波器参数无关。4.3 用一张测试图验证叠加周期条纹再把它滤掉验证频率域滤波最直接的方法是自己造一张含周期噪声的图。下面生成 256x256 的垂直条纹背景中间放一个暗色方块模拟真实缺陷yy, xx np.mgrid[0:256, 0:256] base 128.0 40.0 * np.sin(2 * np.pi * xx / 16.0) # 周期 16 px 的条纹 base[64:192, 64:192] 80.0 # 中间的暗方块 test_img np.clip(base, 0, 255).astype(np.uint8) # 构造高斯低通D0 取 8条纹周期 16px亮斑约在距离中心 16px 处 H gaussian_lp((cv2.getOptimalDFTSize(256), cv2.getOptimalDFTSize(256)), D08) clean frequency_filter(test_img, H)周期 16 像素的条纹在频谱图上对应距离中心约 256/1616 像素位置的一对亮点。D0 取 8 时这对亮点落在滤波器截止半径以外会被显著压制暗方块的边缘属于宽谱信号大部分低频能量保留所以方块轮廓还在只是边缘过渡变宽了。跑完看一眼频谱图和滤波后的图验证标准就两条条纹是否明显变淡甚至消失方块边缘是否还清晰可辨。如果条纹还在说明 D0 太大或滤波器截止不够陡如果方块边缘变得特别糊说明 D0 太小连低频都被砍掉了。造这种合成图的好处是你明确知道噪声频率在哪调参不再是盲试。5. 频率域滤波避坑指南振铃、黑屏、网格纹与黑边的排查记录5.1 理想低通滤波后边缘出现一圈一圈的光晕现象滤波结果图像里的文字、物体边缘附近出现明暗交替的涟漪像加了劣质柔焦效果。原因理想低通在频域是硬截断的矩形窗逆变换到空间域对应 sinc 函数核它有强烈的负旁瓣。图像边缘这种阶跃信号和 sinc 核卷积就会产生过冲和振铃。D0 越小截断半径越窄振铃越往边缘外扩散D0 越大振铃越紧贴在边缘上但不会消失。解决不要用理想低通做实际交付。换成高斯低通直接消除振铃或换巴特沃斯 n2 明显减弱振铃。如果项目考核点就是理想滤波那至少要把 D0 取得相对大一些让截断不那么生硬同时接受一定程度的边缘光晕。5.2 高通滤波后整张图变黑只有轮廓是亮的现象按 H 1 - H_low 构造高通滤波器滤波结果几乎全黑只在强边缘处有一层亮线。原因H_low 的中心直流分量位置是 1所以高通滤波器的直流增益是 1 - 1 0。图像的平均亮度被完全滤掉所有像素值围绕 0 波动显示出来自然是一张黑底轮廓图。这不是 OpenCV 的问题而是高通滤波的数学本质——它把所有平缓信息都归零了。解决如果只想增强边缘而不是把图像变成边缘图用高频提升把高通结果乘以增益再加回原图或者更朴素地用非锐化掩蔽 result cv2.addWeighted(img, 1, img - lowpassed, 1.5, 0)。如果确实需要完整的边缘图做分析那当前结果反而是对的直接 normalize 到 0~255 再用即可。5.3 滤波结果像被切成四块、亮度翻转现象逆变换回来的图像被分成四个象限错位拼接某些区域明暗关系反了整体看起来像拼图错位。原因正变换时做了 np.fft.fftshift滤波在中心坐标系操作但逆变换前忘记做 np.fft.ifftshift直接把中心化的频谱交给 cv2.idft。频谱的象限布局和 idft 期望的布局不一致导致空间域信号错位。解决在 cv2.idft 之前严格执行 np.fft.ifftshift。自检方法是构造一个全 1 滤波器跑完整流程结果应当和原图一致一旦出现错位或亮度异常优先检查 shift 是否成对出现。这个 bug 很难靠肉眼看滤波器代码找出来最好把正逆变换封装成函数强制性配对。5.4 恢复图四周有一圈黑边或边缘出现亮线现象结果图像边缘有一圈明显的黑框或者图像四条边界出现异常的亮线。原因黑边来自 getOptimalDFTSize 引入的 padding 区域没有裁剪干净亮线来自 DFT 的周期延拓假设。图像左右边界在延拓时被硬生生拼在一起原本不连续的强度产生了一个虚假的阶跃频谱里就多出一条十字亮线。解决黑边直接裁剪 result[:rows, :cols] 就行。如果裁剪后边缘亮线仍然明显说明输入图像本身边界太陡可以在 dft 之前先用 cv2.copyMakeBorder 做反射扩展或者说在 padding 前把图像边界做镜面延拓让延拓后的信号周期性更平滑。工业应用里还有一个习惯做法先对整幅图做轻度的边界平滑再进频率域。5.5 彩色图直接调用 cv2.dft 报错或滤波后色调怪异现象对 BGR 三通道彩色图直接调用 cv2.dft 抛异常拆成三个通道分别滤波再合并后整张图颜色偏得厉害。原因cv2.dft 只接受单通道浮点图或双通道复数图三通道输入直接报错。彩色图逐通道滤波后R、G、B 三个通道各自做了独立的归一化原本的比例关系被破坏色调自然偏移。解决工程上最常见的做法是先转 YCrCb只对 Y亮度通道做频率域滤波Cr、Cb 保持不变再合并转回 BGR。因为人眼对亮度细节最敏感色度通道做滤波既慢又容易产生伪彩。代码如下ycrcb cv2.cvtColor(img_bgr, cv2.COLOR_BGR2YCrCb) y, cr, cb cv2.split(ycrcb) y_filtered frequency_filter(y, H) # 对亮度通道滤波 res cv2.merge([y_filtered, cr, cb]) res cv2.cvtColor(res, cv2.COLOR_YCrCb2BGR)如果项目要求必须在 RGB 空间处理另一个可用方案是逐通道滤波但不做归一化只在最后合并时统一做一次全局拉伸。不过这样容易在色度通道里留下振铃伪影YCrCb 方案明显省心。6. 把低通改造成高通与带阻两个实用变体和参数经验6.1 高通用 1 - H_low但一定保住直流分量高通滤波器的构造公式很朴素H_hp 1 - H_low。问题在上面避坑章节提过——这样会把直流归零结果变成黑底边缘图。做边缘增强时正确的改造是把直流分量恢复为 1H_lp gaussian_lp((nrows, ncols), D020) H_hp 1.0 - H_lp H_hp[nrows // 2, ncols // 2] 1.0 # 保住直流避免整图均值归零这个操作付出的是均匀区域不再全黑换来的是原图整体亮度被保留、边缘和纹理被叠加突出。想要更强的锐化效果直接用 result np.clip(img 1.5 * (img - lowpassed), 0, 255) 这种非锐化掩蔽写法更直观增益系数 1.5 可以在 0.5~3 之间调。6.2 带阻用高斯环挖掉周期噪声不对全图动手周期噪声在频谱里是成对亮点低通会把整个高频区都压掉太浪费。更精准的方案是构造一个只围绕目标亮点的阻带环def gaussian_bandstop(shape, D0, width): y, x np.mgrid[0:shape[0], 0:shape[1]] D np.sqrt((x - shape[1] // 2) ** 2 (y - shape[0] // 2) ** 2) band np.exp(-((D - D0) ** 2) / (2 * width ** 2)) return (1.0 - band).astype(np.float32)D0 直接取频谱中亮斑到中心的距离先用第一步的频谱可视化把它“量”出来width 从 D0 的 1/4 开始试。这个滤波器对亮斑附近一小圈做压制其余频段几乎不受影响是处理摩尔纹和扫描波纹的首选方案。6.3 参数不是调出来的是量出来的我现在处理新图像第一件事永远是显示频谱第二件事才动手选滤波器。D0 的单位是频域样本点不是无量纲的魔法数字。同一张图在不同尺寸下同一个 D0 效果完全不同只有先看频谱亮斑的位置你才知道该滤哪里。这套流程跑熟之后频率域滤波的“玄学感”会消失大半剩下的都是可量化的工程判断。希望帮到你。本文还有配套的精品资源点击获取
返回列表