尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

数字图像处理习题库:滤波、均衡化与边缘检测代码复现

发布时间:2026/9/18 12:06:25

资讯中心
01
ARTICLE

数字图像处理习题库:滤波、均衡化与边缘检测代码复现

数字图像处理习题库:滤波、均衡化与边缘检测代码复现
简介这份数字图像处理复习习题库面向高校本科生、考研学生及需要夯实图像处理基础的工程技术人员用于课程期末复习、考研专业课梳理与知识自测。文档以简答、名词解释和计算三类题型组织覆盖图像消噪、图像锐化与平滑、均值滤波与中值滤波的适用噪声差异、伪彩色与假彩色增强的区别、几何失真校正的空间变换与灰度插值步骤、梯度法与Laplacian算子边缘检测的一阶与二阶导数特性、同态滤波流程、直方图均衡化与规定化、图像恢复与图像增强的主客观差别、图像分辨率与显示分辨率及采样量化对图像质量的影响等核心考点并配有典型计算题的变换公式推导练习。资源为1个doc文档压缩包约1.08MB打开即可查阅适合打印后逐题作答与对照答案订正。目前已有787人学习下载可作为课堂笔记之外的补充题库帮助读者在有限时间内串联各章节概念、检验掌握程度并查漏补缺。1. 一份能当错题本用的数字图像处理习题库期末周最怕的不是没资料而是资料只有答案没有推导。这份数字图像处理复习习题库.doc属于后者里比较少见的一类简答题、名词解释、计算题、实训题四段式结构每题下面都带着推演过程比如直方图均衡化的取整映射表、中值滤波前后的逐像素对比、串行通信波特率的单位换算。它不是课件截图拼盘而是一份可以反推出考点分布的题册。适合两类人一是正在备考数字图像处理的学生想找一份能对着公式逐行核对的题库二是工作几年后要做图像预处理模块的工程师需要把遗忘的滤波、锐化、直方图理论捡回来。全文围绕均值滤波与中值滤波的适用边界、直方图均衡化的离散归并、边缘检测的一阶与二阶导数差异这几个核心点展开每个点都还原成能跑的代码或能手算的步骤。2. 均值滤波与中值滤波从噪声模型推导选型2.1 两种噪声的统计特性决定了滤波器的胜负题库里第 3 题问得很直白椒盐噪声和高斯噪声分别适合谁。答案背下来容易理解为什么才是关键。椒盐噪声的特点是幅值近似相等、位置随机图像里既有干净点也有被污染的点中值滤波在一个窗口内排序后取中间值只要污染点不超过窗口像素的一半中值就落在干净值上等于用干净点替换脏点。均值滤波则把污染点算进平均噪声均值不为零误差被摊到整个窗口。高斯噪声相反它作用在每一个像素上幅值近似正态分布均值接近 0。此时窗口内找不到干净点可挑中值的抽样优势消失而均值相当于一次无偏估计多次取值求平均能把均值为 0 的随机扰动抵消掉。题库第 1 题把这一点抽象成了更一般的结论参与平均的像素越多消噪能力越强所以多帧平均和空间模板平均本质是同一件事只是样本来自时间维还是空间维。噪声类型推荐滤波器核心原因代价椒盐噪声中值滤波排序取中值剔除孤立极值点计算量随窗口增大而升高高斯噪声均值滤波零均值随机量可被平均抵消边缘被一并模糊混合噪声先中值后均值先去脉冲再压随机扰动两次滤波细节损失叠加多帧可获取帧间平均时间维样本数 M 可远大于 n×n需要静止场景选型不是死规矩。实际工程里如果噪声模型未知我一般会先对一块平坦区域估方差再决定走哪条路而不是直接套中值。2.2 用 NumPy 复现两种滤波并对比把题库里的定性结论跑成定量结果最省事的做法是用 NumPy 手写滤波核不依赖 OpenCV这样每一行都能对应到课堂公式。import numpy as np def add_salt_pepper(img, ratio): 按比例注入椒盐噪声0 和 255 各占一半 out img.copy() num int(img.size * ratio) coords np.random.choice(img.size, num, replaceFalse) out.flat[coords[:num // 2]] 0 out.flat[coords[num // 2:]] 255 return out def mean_filter(img, k): k x k 均值模板边界用反射填充避免黑边 pad k // 2 p np.pad(img.astype(np.float32), pad, modereflect) out np.zeros_like(img, dtypenp.float32) for i in range(k): for j in range(k): out p[i:i img.shape[0], j:j img.shape[1]] return (out / (k * k)).astype(np.uint8) def median_filter(img, k): k x k 中值模板逐像素排序取中位 pad k // 2 p np.pad(img, pad, modereflect) out np.zeros_like(img) for i in range(img.shape[0]): for j in range(img.shape[1]): window p[i:i k, j:j k] out[i, j] np.median(window) return outadd_salt_pepper用np.random.choice无放回抽取像素坐标保证同一位置不会被重复污染前半赋值 0、后半赋值 255模拟明暗两种脉冲。均值滤波采用先累加后统一除的写法比每步除法少一次浮点运算np.pad的reflect模式让边界像素参与滤波时不会引入人为的 0 值黑边这一点题库里的手算题通常直接规定边界填 0但工程实现中反射填充更合理。中值滤波用双重循环加np.median可读性优先真实项目里会改成sliding_window_view或形态学加速百万像素以上的图直接跑这个版本会明显卡顿。跑一组对比就能复现题库结论对同一张图分别注入椒盐噪声后做 3×3 均值和中值中值的峰值信噪比通常高出好几个分贝换成高斯噪声则反过来。这个实验比背结论有用得多。2.3 关键参数与踩坑点窗口大小是唯一需要调的参数但它不是越大越好。3×3 适合细纹理图像5×5 以上开始明显吞掉边缘7×7 在二值或高对比图像上甚至会把细线滤没。题库第 10 题就是拿 7 像素宽的白条做例子考察 3×3、5×5、7×7 邻域平均后白条会不会消失——当窗口尺寸接近或超过线宽噪声是没了目标也没了。提示中值滤波的窗口尺寸要保证污染像素数小于窗口像素数的一半否则中值本身就可能被噪声占据。椒盐噪声密度 20% 时3×3 窗口理论余量已经接近极限建议换 5×5。另一个容易被忽略的点是数据类型。用uint8做累加会溢出必须像上面代码那样先转float32。中值滤波不涉及求和可以直接在整数域操作这也是它比均值滤波省内存的一个细节。最后彩色图像不要对 RGB 三通道各自滤波后拼接色度通道的排序结果可能引入新的杂色正确做法是转成 YCbCr 或 Lab只对亮度通道滤波。3. 直方图均衡化离散灰度级下为什么得不到平坦直方图3.1 从累积分布到取整映射的完整推演题库第 3 题给出了一组 10 灰度级的原始直方图[1, 4, 5, 5, 3, 1, 3, 3, 2, 9]总和 36 个像素。均衡化的标准做法是先归一化成概率再求累积分布最后乘以最大灰度级取整得到映射关系。这套流程在连续情况下能保证输出直方图完全均匀但在离散情况下多个相近的累积值会被取整到同一个灰度级发生灰度级归并。用代码把这个过程完整走一遍顺便验证题库里那张映射表。import numpy as np hist np.array([1, 4, 5, 5, 3, 1, 3, 3, 2, 9], dtypenp.float64) total hist.sum() # 总像素数 36 pdf hist / total # 归一化概率 cdf np.cumsum(pdf) # 累积分布 L len(hist) - 1 # 最大灰度级 9 mapping np.round(cdf * L).astype(int) # 取整得到映射关系 print(累积分布:, np.round(cdf, 4)) print(映射关系:, mapping) # 统计均衡化后的新直方图 new_hist np.zeros_like(hist) for old, new in enumerate(mapping): new_hist[new] hist[old] print(均衡后直方图:, new_hist) print(均衡后概率:, np.round(new_hist / total, 4))total取 36 是因为直方图各分量之和就是像素总数这一步错了后面全错。np.cumsum代替手写循环累积分布的物理含义是灰度小于等于当前级的像素占比。mapping里出现的重复值就是归并点比如原始灰度 3 和 4 可能同时映射到 4合并后该灰度级的概率变成两者之和自然就比相邻级高出许多直方图不再平坦。映射关系会得到类似0→0, 1→1, 2→3, 3→4, 4→4, 5→5, 6→5, 7→6, 8→7, 9→9的结果和题库答案一致。可以看到 3、4 归并到 45、6 归并到 5这就是离散均衡化无法完全平坦的直接证据。题库第 10 题问的正是这一点灰度级的离散性导致归并结果只是趋于平坦。3.2 均衡化与规定化的差异与选择题库第 8 题把均衡化和规定化放在一起比较。均衡化不需要人工干预输出是固定的适合每张图都不同的批量处理场景规定化需要指定目标直方图形状比如高灰度区域概率更大适合有明确亮度区间的场景——题库里说规定化在高灰度区域用较大的规定化函数结果图像比均衡化更亮、细节更清楚说的就是这个道理。两者的数学基础相同都是通过改变直方图形状来拉伸对比度只是规定化多做了一步从均衡结果反查目标累积分布的映射。实现上规定化等价于两次均衡先把原图均衡一次再把目标直方图均衡一次最后用后者的反函数去查前者。用代码描述就是map2[inv_map1[pixel]]理解了这层嵌套题库里所有的直方图题都不需要背步骤。方法输入输出直方图适用场景直方图均衡化原图趋于均匀自适应批量增强、对比度未知直方图规定化原图 目标直方图逼近指定形状需要特定亮度分布多帧平均M 帧同一场景噪声方差降至 1/M静态场景、有连续帧注意均衡化处理的是整幅图的全局对比度。如果图像存在明显的光照不均比如一侧过曝一侧过暗全局均衡会把亮区拉爆这时应先做同态滤波或分块均衡。题库第 7 题提到的同态滤波作用就是压缩照度分量、保留反射分量和均衡化不是替代关系。3.3 用 OpenCV 快速验证与参数化手写一遍是为了理解实际验证用 OpenCV 一行即可但要留意它内部做了一次额外的归一化结果和手算可能略有出入。import cv2 import numpy as np img cv2.imread(input.jpg, cv2.IMREAD_GRAYSCALE) # 标准全局均衡化 eq cv2.equalizeHist(img) # 对比度受限自适应均衡化抑制平坦区域噪声放大 clahe cv2.createCLAHE(clipLimit2.0, tileGridSize(8, 8)) adap clahe.apply(img) # 统计均衡前后的直方图熵熵越大说明灰度分布越均匀 def entropy(image): h cv2.calcHist([image], [0], None, [256], [0, 256]).ravel() p h / h.sum() p p[p 0] return -np.sum(p * np.log2(p)) print(原图熵:, entropy(img)) print(均衡后熵:, entropy(eq)) print(CLAHE 后熵:, entropy(adap))clipLimit2.0是 CLAHE 的对比度裁剪阈值值越大增强越强但噪声也越明显一般取 2.0 到 4.0tileGridSize(8, 8)把图像切成 8×8 的块分别均衡块越小局部适应性越强但块边界可能出现明显的接缝。熵值用于定量判断均衡效果灰度分布越均匀熵越大把三种方法的熵排一下序就能看出全局均衡在多数图像上确实提升了分布均匀度。需要留意的是cv2.equalizeHist只接受单通道 8 位图彩色图要先转灰度或转 YCrCb 只处理 Y 通道。另外它内部按 256 级计算和用 10 级手算的结果在取整点上会有细微差异核对题库答案时以手算为准。4. 边缘检测与几道计算题的标准化解法4.1 梯度算子与 Laplacian 的模板差异题库第 6 题的答案点到了一阶和二阶导数的本质区别梯度算子用一阶导数认为灰度剧烈变化的极大值点是边缘Laplacian 用二阶导数认为零交叉点是边缘。这个区别决定了它们对噪声的敏感程度不同——求导阶数越高对高频噪声的放大越厉害所以 Laplacian 对噪声更敏感通常要先做高斯平滑这正是 LoG 算子的由来。用代码把两个模板的响应值算出来比看公式直观。梯度算子常见的简化模板是[-1, -1, 1; 1, 1, 1; -1, -1, 1]这类形式Laplacian 则用[1, 1, 1; 1, -4, 1; 1, 1, 1]。注意 Laplacian 模板的系数和为 0意味着平坦区域的响应严格为 0只在灰度变化处产生正负值边缘就藏在正负交界的零交叉点上。import numpy as np from scipy.signal import convolve2d img np.array([[8, 9, 0, 7, 6], [3, 5, 6, 1, 5], [8, 4, 0, 2, 9], [0, 4, 2, 1, 2], [3, 4, 1, 2, 1]], dtypenp.float64) # 水平方向的梯度模板简化形式 grad np.array([[-1, -1, -1], [ 0, 0, 0], [ 1, 1, 1]], dtypenp.float64) lap np.array([[ 1, 1, 1], [ 1, -4, 1], [ 1, 1, 1]], dtypenp.float64) g_res convolve2d(img, grad, modesame, boundaryfill, fillvalue0) l_res convolve2d(img, lap, modesame, boundaryfill, fillvalue0) print(梯度响应:\n, g_res) print(Laplacian 响应:\n, l_res)modesame保证输出尺寸与原图一致符合题库第 12 题给出与图像尺寸一致的结果的要求boundaryfill, fillvalue0对应题库反复出现的边界像素填 0约定。梯度响应里的最大值位置就是边缘位置Laplacian 响应里正负过零点才是边缘两者在理想阶跃边缘上会给出接近的位置但在斜边缘和噪声区域分歧很大。这也解释了为什么 Canny 要先把梯度做非极大值抑制而 LoG 必须先平滑。4.2 存储容量与传输时间的单位换算套路题库第 9、10、11 题和串行通信那题都属于给参数算容量或时间公式固定坑全在单位上。帧大小计算宽 × 高 × 每像素位数 / 8得到字节数/ 1024得 KB再/ 1024得 MB。256 级灰度是 8 位32 位真彩色是 4 字节别把 32 位当成 32 个灰度级。题库里 1024×1024、256 级灰度的图数据量是1024×1024×8 8388608位约 1 MB。传输时间计算要先算帧长一帧包含起始位、8 个信息位、结束位共 10 位。题库的1024×1024×(82)/56000就是先把像素位宽补上 2 位开销再除以波特率。这里要分清波特率和比特率题库定义波特率就是每秒传输的比特数所以可以直接除。def frame_bits(width, height, bit_per_pixel, overhead0): 计算一幅图像的总位数overhead 为每像素额外开销位 return width * height * (bit_per_pixel overhead) def transfer_seconds(bits, baud_bps): return bits / baud_bps # 1024x1024 灰度图帧开销 2 位56Kbps 信道 bits frame_bits(1024, 1024, 8, overhead2) print(总位数:, bits) print(56K 信道耗时(秒):, transfer_seconds(bits, 56000)) # 视频帧存储512x512 真彩色32 位每秒 30 帧 per_frame_bytes 512 * 512 * 32 / 8 per_second per_frame_bytes * 30 print(每秒字节:, per_second) print(40GB 可存秒数:, 40 * 1024**3 / per_second) print(10 倍压缩后可存秒数:, 40 * 1024**3 / (per_second / 10))frame_bits里overhead参数就是为串行帧开销准备的题库里的82对应这里传overhead2。存储容量换算统一用 1024 进制机械硬盘厂商标注常用 1000 进制题目没说就按 1024。压缩比 10 直接作用在每秒字节数上注意是可存秒数变成 10 倍而不是容量变成 10 倍这两个说法容易在写答案时混。提示二值图像的白条宽度那类题先换算白条宽度占多少个像素再和滤波窗口尺寸比较。窗口大于线宽时白条会被填掉这是判断答案能否成立的最快方法不用逐像素算。4.3 中值滤波在具体图像上的手动验证题库第 13 题给了一张 8×8 的灰度矩阵要求做中值滤波。手算时按行滑动窗口每个窗口取第 5 大9 个元素的中位数可以先用代码验证再对照答案。import numpy as np img np.array([[1, 1, 1, 8, 7, 4, 2, 7], [2, 3, 2, 5, 5, 3, 3, 3], [3, 2, 5, 5, 3, 3, 3, 3], [2, 5, 5, 6, 4, 6, 3, 2], [5, 5, 4, 5, 5, 8, 2, 3], [4, 6, 7, 8, 2, 3, 4, 5]]) def median_filter_manual(img, k3): h, w img.shape pad k // 2 p np.pad(img, pad, modeconstant, constant_values0) out np.zeros_like(img) for i in range(h): for j in range(w): out[i, j] np.median(p[i:i k, j:j k]) return out print(median_filter_manual(img))np.pad用constant_values0对应题库边界像素填 0np.median自动处理奇数窗口的中位数。中值滤波的非线性特性意味着它不满足叠加原理所以不能像均值那样靠卷积快速实现必须逐点排序。这也是它在实时系统里通常被限定在小窗口的原因。5. 从习题到工程给滤波和均衡化做参数化封装习题做完一圈真正能用起来的是把它封装成带参数、能批量验证的模块。把前面零散的函数组织成一个类输入输出路径、窗口大小、滤波类型都做成配置项跑一次就能同时输出滤波结果和量化指标。import cv2 import numpy as np class PreprocessPipe: def __init__(self, methodmedian, ksize3, use_claheFalse): self.method method self.ksize ksize self.use_clahe use_clahe def _filter(self, gray): if self.method median: return cv2.medianBlur(gray, self.ksize) if self.method mean: return cv2.blur(gray, (self.ksize, self.ksize)) if self.method gaussian: return cv2.GaussianBlur(gray, (self.ksize, self.ksize), 0) raise ValueError(f未知滤波方法: {self.method}) def run(self, path): gray cv2.imread(path, cv2.IMREAD_GRAYSCALE) out self._filter(gray) if self.use_clahe: clahe cv2.createCLAHE(clipLimit2.0, tileGridSize(8, 8)) out clahe.apply(out) return gray, out def psnr(a, b): 计算峰值信噪比用于比较滤波前后与参考图的差距 mse np.mean((a.astype(np.float64) - b.astype(np.float64)) ** 2) if mse 0: return float(inf) return 10 * np.log10(255 ** 2 / mse) pipe PreprocessPipe(methodmedian, ksize5, use_claheTrue) src, dst pipe.run(noisy.jpg) print(PSNR:, psnr(src, dst))_filter用方法名做分发ksize必须传奇数OpenCV 的medianBlur和blur都要求如此传偶数会直接报错。use_clahe开关把滤波和对比度增强串成一条流水线对应题库实训题里组织成一个处理流程的要求——先做什么后做什么就是靠这种开关组合去验证的。psnr用来量化滤波是否过度信噪比太低说明欠滤波结构相似度掉太多说明过滤波两个指标一起看比单看一个可靠。参数标定可以用网格搜索把窗口尺寸在 3、5、7 之间遍历滤波方法在 median、mean、gaussian 之间遍历每种组合算 PSNR 和运行耗时最后按噪声类型 → 最优组合整理成一张表。椒盐噪声占比超过 15% 时median 5×5 几乎总是最优高斯噪声下 mean 或 gaussian 更稳。把这张表存成配置下次直接查不用重新试。注意PSNR 对亮度偏移不敏感对模糊敏感比较不同窗口大小时它偏向小窗口。做选型时建议再补一个边缘保持度指标比如用 Canny 提取边缘后统计边缘像素量的下降比例下降越多说明细节丢得越厉害。最后留一个可复现的验证方法拿一份自带噪声的样图固定随机种子生成椒盐和高斯两种污染版本把三种滤波和各窗口组合的 PSNR、耗时、边缘保持度打包成 CSV用同一份数据画曲线。这样得到的结论是可以写进项目文档、也可以拿去对答案的比背题库原话靠谱得多。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。