☰
数字图像处理试题及答案.pdf:用Python代码复现图像处理算法
2026/10/10 16:06:07 网站建设 项目流程

简介:这份《数字图像处理试题及答案》PDF面向高校计算机、电子信息类专业学生及备考数字图像处理课程的读者,用于期末复习、自测与知识点查漏补缺。内容以试卷形式组织,覆盖填空题、选择题、判断题、简答题与问答题,涉及图像增强、直方图均衡化、图像压缩与编码冗余、图像复原、边缘检测、彩色模型等核心考点,并附有参考答案与推导过程。资源包共1个PDF文件,约123KB,篇幅紧凑,便于打印或移动端随时翻阅。其中简答题与问答题部分给出了逆滤波噪声处理、亮度适应、梯度算子与Laplacian算子异同、高频加强与直方图均衡化顺序等典型题目的完整解答,适合对照梳理答题思路。目前已有1137人学习下载,可作为课程复习与考前突击的实用参考资料。

1. 数字图像处理试题及答案.pdf:从一份复习资料到能跑通的图像处理知识体系

很多人第一次搜「数字图像处理试题及答案.pdf」,其实不是想找一份死记硬背的题库,而是被图像处理这门课的考试逼到了墙角——傅里叶变换、直方图均衡、边缘检测、形态学操作,概念一堆,公式一墙,做题时却不知道这些算法在真实代码里长什么样。我当年也是这么过来的,后来发现一个反直觉的结论:把试题当代码题来做,比当文科题来背,效率高得多。这份资料真正能解决的问题,是帮你把「会算」和「会写」之间的鸿沟填上。它适合正在备考的学生,也适合想系统梳理图像处理基础、但不想啃完整本教材的开发者。接下来我会按「概念怎么理解、代码怎么复现、参数怎么调、坑在哪」这条线,把这份试题资料背后的知识体系拆开讲清楚。

2. 从试题到代码:把每道题还原成可运行的 Python 片段

2.1 为什么试题里的算法值得用代码重写一遍

数字图像处理的试题有个特点:它考的不是记忆,而是你对算法流程的理解。比如一道「对图像进行直方图均衡化」的题,试卷上可能只让你写出变换函数,但如果你用代码跑一遍,就会立刻明白为什么均衡化之后对比度会提升、为什么有些图会变得过曝。我一般建议把试题分成四类:灰度变换类、滤波类、频域类、形态学类。每一类挑两三道典型题,用 Python 加 OpenCV 或 NumPy 重写,你会发现原本模糊的概念会变得非常具体。

重写的时候不要追求一次写对,先让代码跑起来,再对照试题里的中间结果去验证。比如试题里给了某个 3×3 邻域的均值滤波结果,你就用代码对同样的小矩阵做一遍,看输出是否一致。这种「小矩阵验证法」是排查理解偏差最快的方式,比看十遍书都管用。

2.2 用 NumPy 复现灰度变换与直方图均衡

灰度变换是试题里出现频率最高的题型之一,常见的有线性拉伸、对数变换、幂律变换。下面这段代码把三种变换放在一起,方便对比效果。

import numpy as np import cv2 # 读取图像并转为灰度图 img = cv2.imread('input.jpg', cv2.IMREAD_GRAYSCALE) if img is None: raise FileNotFoundError('请确认 input.jpg 在当前目录下') # 归一化到 [0, 1],避免后续计算溢出 img_norm = img.astype(np.float32) / 255.0 # 1. 线性拉伸:把 [50, 200] 映射到 [0, 255] a, b = 50, 200 linear = np.clip((img - a) / (b - a), 0, 1) # 2. 对数变换:压缩高灰度区,扩展低灰度区 log_trans = np.log1p(img_norm) / np.log(2.0) # 3. 幂律变换(伽马校正):gamma < 1 提亮暗部 gamma = 0.5 power = np.power(img_norm, gamma) # 转回 uint8 保存 for name, data in [('linear', linear), ('log', log_trans), ('power', power)]: out = (data * 255).astype(np.uint8) cv2.imwrite(f'out_{name}.png', out)

这段代码的关键在于归一化。很多试题只给公式,不强调数值范围,实际写代码时如果直接用 uint8 做对数或幂运算,很容易溢出或截断。参数方面,线性拉伸的 a 和 b 决定了你要保留哪一段灰度,a 越大暗部被压得越狠;对数变换的底数我习惯用 2,也可以用自然对数,区别只是压缩程度;伽马值小于 1 提亮暗部,大于 1 压暗亮部,试题里常考伽马取 0.4、0.8、1.5 时的曲线形状,你跑一遍就能记住。

直方图均衡化的代码更短,但理解起来需要一点概率基础。OpenCV 的equalizeHist直接可用,但试题往往要求你手写累积分布函数。手写版本如下:

def my_equalize(img): hist, _ = np.histogram(img.flatten(), 256, [0, 256]) cdf = hist.cumsum() # 跳过累积分布为 0 的灰度级,避免除零 cdf_m = np.ma.masked_equal(cdf, 0) cdf_m = (cdf_m - cdf_m.min()) * 255 / (cdf_m.max() - cdf_m.min()) cdf = np.ma.filled(cdf_m, 0).astype('uint8') return cdf[img] eq = my_equalize(img) cv2.imwrite('out_eq.png', eq)

这里有个容易翻车的点:cdf.min()在掩码数组上取的是非零最小值,如果你直接对原始 cdf 做归一化,第一段会出错。试题里通常不会考这个细节,但实际写代码时这是血泪经验。

2.3 空间滤波:从试题里的 3×3 模板到可调参数的卷积

空间滤波的试题一般会给你一个模板,让你计算某个像素的输出。用代码复现时,核心是理解卷积和相关的区别,以及边界怎么处理。

import numpy as np import cv2 img = cv2.imread('input.jpg', cv2.IMREAD_GRAYSCALE) # 定义一个 3×3 均值模板 kernel_mean = np.ones((3, 3), np.float32) / 9.0 # 高斯模板,sigma 可调 def gaussian_kernel(size=3, sigma=1.0): ax = np.arange(-(size//2), size//2 + 1) xx, yy = np.meshgrid(ax, ax) kernel = np.exp(-(xx**2 + yy**2) / (2 * sigma**2)) return kernel / kernel.sum() kernel_gauss = gaussian_kernel(3, 1.0) # 用 filter2D 做相关(OpenCV 默认是相关,不是严格卷积) mean_filtered = cv2.filter2D(img, -1, kernel_mean) gauss_filtered = cv2.filter2D(img, -1, kernel_gauss) cv2.imwrite('out_mean.png', mean_filtered) cv2.imwrite('out_gauss.png', gauss_filtered)

参数说明:均值模板的系数全为 1/9,作用是平滑噪声但会模糊边缘;高斯模板的 sigma 越大,平滑越强,试题里常考 sigma=0.5、1.0、2.0 时模板系数的变化。边界处理默认是BORDER_DEFAULT,实际做试题时如果要求零填充,需要手动指定borderType=cv2.BORDER_CONSTANT。另外注意 OpenCV 的filter2D做的是相关,不是卷积,如果试题明确要求卷积,需要把模板旋转 180 度,这一点在频域滤波的试题里经常被拿来设陷阱。

2.4 频域滤波:试题里的傅里叶变换怎么用 NumPy 验证

频域部分的试题让很多人头疼,因为公式抽象。用 NumPy 的 FFT 跑一遍,再显示频谱图,理解会直观很多。

import numpy as np import cv2 import matplotlib.pyplot as plt img = cv2.imread('input.jpg', cv2.IMREAD_GRAYSCALE) # 二维傅里叶变换 f = np.fft.fft2(img) fshift = np.fft.fftshift(f) # 计算幅度谱并做对数变换,否则一片黑 magnitude = 20 * np.log(np.abs(fshift) + 1) # 理想低通滤波:半径 D0 以内的保留 rows, cols = img.shape crow, ccol = rows // 2, cols // 2 D0 = 30 mask = np.zeros((rows, cols), np.uint8) for i in range(rows): for j in range(cols): if (i - crow)**2 + (j - ccol)**2 <= D0**2: mask[i, j] = 1 fshift_filtered = fshift * mask f_ishift = np.fft.ifftshift(fshift_filtered) img_back = np.fft.ifft2(f_ishift) img_back = np.abs(img_back) plt.subplot(121), plt.imshow(magnitude, cmap='gray') plt.subplot(122), plt.imshow(img_back, cmap='gray') plt.show()

这段代码里,fftshift把零频移到中心,方便做圆形掩膜。D0 是截止频率,试题里常考 D0 取不同值时振铃效应的强弱。理想低通滤波会产生明显的振铃,这是因为它对应的空间域模板是 sinc 函数。实际做题时如果要求用巴特沃斯或高斯低通,只需要把 mask 的计算公式换掉,代码结构不变。注意np.abs取模后还要做对数变换才能看清频谱,直接显示幅度谱会是一片黑,这是新手最容易踩的坑。

3. 试题里高频出现的参数与公式:怎么记、怎么调、怎么验证

3.1 直方图规定化与均衡化的区别

直方图规定化是试题里的进阶题型,它要求把图像变换成指定的直方图,而不是均匀分布。很多人在这一步混淆了均衡化和规定化的步骤。均衡化是规定化的特例,规定化需要多做一步:先对原始图像做均衡化,再对目标直方图做均衡化,然后建立映射。用代码验证时,可以先生成一个目标直方图,比如双峰分布,然后看输出图像的直方图是否逼近目标。

参数上,规定化的关键是对应灰度级的映射表。如果目标直方图有多个峰值,映射表可能出现多对一的情况,这时候需要取最接近的灰度级。试题里常给一个简单的目标直方图,让你手算映射表,用代码跑一遍就能确认自己算得对不对。

3.2 边缘检测算子的阈值选择

Sobel、Prewitt、Canny 是试题里的常客。Sobel 和 Prewitt 的模板固定,主要考计算;Canny 则涉及双阈值,参数选择更灵活。Canny 的低阈值和高阈值比例一般在 1:2 到 1:3 之间,低阈值太小会引入噪声,太大则漏掉弱边缘。用代码调参时,可以先固定高阈值,然后逐步降低低阈值,观察边缘图的变化。

import cv2 img = cv2.imread('input.jpg', cv2.IMREAD_GRAYSCALE) # Canny 双阈值:低阈值 50,高阈值 150 edges = cv2.Canny(img, 50, 150) cv2.imwrite('out_canny.png', edges)

试题里如果让你比较不同算子的效果,重点看边缘的连续性和抗噪性。Sobel 对噪声敏感,Canny 因为做了非极大值抑制和双阈值,边缘更细更连续。实际写代码时,Canny 之前一般会加高斯模糊,这一步试题里可能省略,但工程上不能省。

3.3 形态学操作的顺序与结构元

腐蚀、膨胀、开运算、闭运算,试题里经常考顺序和结构元形状。开运算是先腐蚀后膨胀,用来去小亮点;闭运算是先膨胀后腐蚀,用来填小孔。结构元的大小和形状直接影响结果,常用的有矩形、椭圆、十字形。

import cv2 import numpy as np img = cv2.imread('input.jpg', cv2.IMREAD_GRAYSCALE) _, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 定义 3×3 矩形结构元 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) opened = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel) closed = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel) cv2.imwrite('out_open.png', opened) cv2.imwrite('out_close.png', closed)

参数说明:结构元越大,效果越强,但也会抹掉更多细节。试题里常考 3×3 和 5×5 的对比,5×5 的去噪能力更强,但可能把细小的目标也去掉。另外注意二值化阈值的选择,阈值不对,形态学操作的结果会完全偏离预期。

4. 避坑与排查:做试题和写代码时最容易翻车的五个地方

4.1 现象:直方图均衡化后图像全白或全黑

原因:输入图像已经是高对比度,或者累积分布函数计算时没有跳过零值,导致映射表出错。解决:先检查图像的直方图分布,如果灰度集中在两端,均衡化效果本来就不明显;手写均衡化时务必用掩码数组处理零值,或者直接用 OpenCV 的equalizeHist对照。

4.2 现象:频域滤波后图像出现周期性条纹

原因:理想低通滤波的振铃效应,或者fftshift和ifftshift没有配对使用。解决:改用巴特沃斯或高斯低通,振铃会明显减弱;检查代码中是否在逆变换前做了ifftshift,顺序错了会导致频谱错位。

4.3 现象:Canny 边缘检测结果全是噪点

原因:低阈值设得太低,或者没有做高斯模糊。解决:先把低阈值提高到高阈值的 1/3 到 1/2,再逐步调整;在 Canny 之前加一个 5×5 的高斯模糊,sigma 取 1.0 到 1.5。

4.4 现象:形态学操作后目标消失

原因:结构元太大,或者腐蚀次数过多。解决:先用 3×3 结构元试,观察结果再决定是否增大;如果目标是细长形状,改用十字形或椭圆形结构元,避免矩形结构元把目标切断。

4.5 现象:试题里的卷积结果和代码跑出来的不一致

原因:OpenCV 的filter2D做的是相关,不是卷积;或者边界处理方式不同。解决:如果试题要求卷积,把模板旋转 180 度再传给filter2D;边界处理手动指定为BORDER_CONSTANT并设置填充值,与试题的零填充保持一致。

5. 把试题资料变成自己的图像处理工具箱:一个可复用的验证脚本

试题做完一遍,如果不整理,过两周就忘。我的习惯是写一个统一的验证脚本,把常见的操作封装成函数,每次遇到新的试题,只需要改参数就能快速验证。下面这个脚本框架可以直接拿去用。

import numpy as np import cv2 import matplotlib.pyplot as plt class ImageLab: def __init__(self, path): self.img = cv2.imread(path, cv2.IMREAD_GRAYSCALE) if self.img is None: raise FileNotFoundError(f'无法读取 {path}') self.img_norm = self.img.astype(np.float32) / 255.0 def show(self, *imgs, titles=None): n = len(imgs) titles = titles or [f'img{i}' for i in range(n)] for i, (im, t) in enumerate(zip(imgs, titles), 1): plt.subplot(1, n, i) plt.imshow(im, cmap='gray') plt.title(t) plt.axis('off') plt.show() def linear_stretch(self, a=50, b=200): return np.clip((self.img - a) / (b - a), 0, 1) def gamma_correct(self, gamma=0.5): return np.power(self.img_norm, gamma) def gaussian_blur(self, ksize=5, sigma=1.0): return cv2.GaussianBlur(self.img, (ksize, ksize), sigma) def canny(self, low=50, high=150): blurred = self.gaussian_blur(5, 1.0) return cv2.Canny(blurred, low, high) def fft_lowpass(self, D0=30): f = np.fft.fft2(self.img) fshift = np.fft.fftshift(f) rows, cols = self.img.shape crow, ccol = rows // 2, cols // 2 mask = np.zeros((rows, cols), np.uint8) y, x = np.ogrid[:rows, :cols] mask[(y - crow)**2 + (x - ccol)**2 <= D0**2] = 1 fshift = fshift * mask f_ishift = np.fft.ifftshift(fshift) img_back = np.abs(np.fft.ifft2(f_ishift)) return img_back # 使用示例 lab = ImageLab('input.jpg') lab.show(lab.img, lab.gamma_correct(0.5), lab.canny(50, 150), titles=['原图', '伽马0.5', 'Canny'])

这个类的价值在于把参数和操作分离,试题里改一个参数,你只需要改调用时传的值,不用重写整个流程。我一般还会在show里加一个保存功能,方便把结果贴到笔记里。另外,fft_lowpass里用np.ogrid生成坐标网格,比双重循环快很多,这也是从试题的朴素写法进化到工程写法的一个小技巧。

最后说一个我自己的教训:早期做试题时,我总想一次把所有公式都推导清楚再写代码,结果卡在数学上,进度很慢。后来改成先跑代码看结果,再回头补公式,反而理解得更快。图像处理这门课,视觉反馈比公式推导更能建立直觉。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询