ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

数字图像处理期末复习指南:核心考点与Python代码实战

数字图像处理期末复习指南:核心考点与Python代码实战 期末考试临近很多同学在复习《数字图像处理》时都有同感上课听老师讲概念好像都明白一到自己做实验、画直方图、写滤波代码就开始头皮发麻翻开书又发现知识点又多又碎空域滤波、频域滤波、图像分割、形态学处理……每章都有考点却不知道哪些是重点。这篇文章正是为你准备的。我会结合合肥学院《数字图像处理》课程的常见教学范围参考冈萨雷斯《数字图像处理》这本经典教材的体系把整门课的复习框架、核心公式、典型算法、实验代码、期末常见题型全部梳理一遍。不管你是想期末不挂科还是准备考研复试这篇文章都能直接当复习提纲用。为了做到“复习可操作”我会尽量把每个算法的原理、数学表达、代码实现、适用场景放在一起讲不搞空对空的概念复述。文末还整理了一份高频考点自查表和一批容易被忽略的细节帮你考前快速扫描知识盲区。1. 课程到底在学什么先建立整体框架1.1 数字图像处理不是“P图”很多同学第一次接触这门课时会误以为数字图像处理就是 Photoshop 修图。这个理解说对了一半但不完整。数字图像处理Digital Image Processing是用计算机对图像信号进行数字化后再通过数学和算法手段完成去噪、增强、复原、压缩、分割、特征提取等操作的过程。它处理的对象是“数字图像”也就是已经被离散化后的二维矩阵数据。从课程结构上看合肥学院的《数字图像处理》通常覆盖这样一条主线图像如何变成数字采样、量化、像素间关系图像质量如何改善灰度变换、直方图处理、空间滤波、频域滤波图像内容如何恢复图像复原、退化模型图像中的物体如何分离边缘检测、阈值分割、区域分割图像结构如何分析形态学处理、描述子这个顺序刚好也是冈萨雷斯教材的目录顺序也是大多数高校期末考试的出题顺序。1.2 数字图像处理与相关领域的关系复习前建议先把一些容易混淆的方向划清楚方向核心任务典型工具/方法图像处理图像到图像改善视觉效果滤波、增强、复原图像分析图像到数值/符号描述图像内容分割、特征提取、测量计算机视觉图像到语义理解感知三维世界目标检测、识别、三维重建机器学习/深度学习数据驱动模型替代手工设计CNN、Transformer期末课程重点在前两项。考试中如果出现“图像处理与计算机视觉的区别和联系”能用自己的话说清楚即可不必过度展开。理解这层关系还有一个好处考研复试时老师很喜欢问“你对数字图像处理这个方向的理解”你如果能从“底层处理到高层理解”这个层次讲清楚面试印象会好很多。1.3 为什么很多同学觉得这门课难《数字图像处理》的难点不在代码而在数学。卷积、傅里叶变换、概率统计这些大一、大二学过的数学工具到了这门课里突然全部“活”了过来空间滤波的本质是卷积运算频域滤波的本质是傅里叶变换与频域乘法图像复原里的维纳滤波需要高斯噪声模型与最小均方误差估计图像分割里的Otsu阈值要用类间方差最大化。所以复习这门课我建议的顺序是先理解物理含义再看数学表达最后回到代码验证。如果你一上来就死记公式考试时换个条件你就不会了。2. 复习环境准备把 Python OpenCV 搭好复习数字图像处理动手实验比只看书有效得多。期末前你至少需要能把书本上的直方图均衡化、中值滤波、Canny边缘检测这些基础实验跑通。本文代码统一用 Python OpenCV。2.1 环境版本建议版本不一定必须和我完全一致只要能运行 OpenCV 即可。下面是我建议的基础环境操作系统Windows 10/11 或 Ubuntu 20.04/22.04 Python3.8 ~ 3.11 OpenCV4.5.0 及以上 NumPy1.21 及以上 Matplotlib3.5 及以上如果你的电脑上还没装 Python 环境可以安装 Anaconda然后使用 conda 创建独立环境避免把系统环境搞乱。2.2 创建虚拟环境与安装依赖打开终端Windows 下可以使用 Anaconda Prompt依次输入下面命令conda create -n dip python3.9 -y conda activate dip pip install opencv-python opencv-contrib-python numpy matplotlib安装完成后验证一下import cv2 import numpy as np import matplotlib.pyplot as plt print(OpenCV 版本, cv2.__version__) print(NumPy 版本, np.__version__)能够正常输出版本号说明环境已经可以用了。2.3 关于实验图片的准备复习时建议准备两张图一张灰度图例如lena.png或cameraman.tif用于灰度变换、直方图、滤波实验一张有噪声的图可以自己给原图添加高斯噪声或椒盐噪声用于复原实验。如果没有标准测试图也可以用下面代码生成一张测试图import cv2 import numpy as np img np.zeros((256, 256), dtypenp.uint8) img[50:200, 50:200] 200 img cv2.GaussianBlur(img, (5, 5), 0) # 添加椒盐噪声 np.random.seed(0) noise np.random.rand(256, 256) img_noise img.copy() img_noise[noise 0.05] 0 img_noise[noise 0.95] 255 cv2.imwrite(test_image.png, img_noise) print(测试图已生成)代码中的GaussianBlur是高斯平滑用于模拟模糊退化后续做图像复原实验可以直接用这张图。3. 核心考点分块拆解从图像数字化到频域处理下面我按照期末复习的常见顺序把必考的核心知识分成若干个模块每个模块讲清楚三件事它是什么、它的核心公式/方法是什么、考试通常怎么出题。3.1 图像数字化采样、量化与像素关系这是课程第一章内容概念性强小题频出。什么是采样与量化模拟图像要变成数字图像必须经过两个步骤采样在空间上对连续的图像函数进行离散化即用有限个点表示图像。量化把采样点上的连续灰度值取整成有限个离散级别。这两个概念常考简答题例如“说明采样和量化的含义及它们对图像质量的影响”。数字图像表示一幅大小为 M×N 的灰度图可以用矩阵表示为| f(0,0) f(0,1) ... f(0,N-1) | f | f(1,0) f(1,1) ... f(1,N-1) | | ... ... ... ... | | f(M-1,0) f(M-1,1) ... f(M-1,N-1) |灰度级通常取 2 的整数次幂常见 256 级即每个像素占 8 bit。存储一幅 M×N、灰度级为 2^k 的图像需要的比特数b M × N × k这是期末计算题的常客。比如一幅 1024×768、256 级灰度的图像占多少比特b 1024 × 768 × 8 6,291,456 bit 786,432 Byte 768 KB注意单位换算不要出错尤其是“位”和“字节”的区别。像素间的基本关系这一节里最容易出选择题或简单计算题的是“像素间距离”的定义。欧氏距离Euclidean Distance实际几何距离。城区距离City-Block DistanceD4水平/垂直方向步行距离。棋盘距离Chessboard DistanceD88 邻域内前进所需步数。定义公式为D4 |x - s| |y - t| D8 max(|x - s|, |y - t|)例如坐标 (2,3) 与 (5,7) 之间的 D4 距离为 |2-5||3-7| 7D8 距离为 max(3, 4) 4。相邻像素4-邻域、8-邻域、对角邻域也是高频选择题画图记忆即可。3.2 灰度变换与直方图处理最实用的入门模块这一章是大部分同学第一次接触“增强”的地方也是实验课最常安排的内容。灰度变换的常见函数图像增强中常用的灰度变换函数有线性变换s a * r b其中 r 是原灰度s 是变换后灰度。对数变换s c * log(1 r)常用于扩展暗部细节。幂次变换s c * r^γγ1 扩展暗部γ1 扩展亮部。反转变换s L - 1 - r相当于负片效果。复习时要能根据题意判断选用哪个函数。比如题目说“图像暗部细节不清楚应该用什么变换来增强”优先考虑对数变换或 γ1 的幂次变换。直方图的概念灰度直方图是一个一维离散函数表示图像中每种灰度级出现的像素个数h(r_k) n_k其中 r_k 是第 k 级灰度n_k 是灰度级为 r_k 的像素数量。直方图能反映图像的对比度特征直方图窄且集中在低灰度区域图像偏暗。直方图窄且集中在高灰度区域图像偏亮。直方图成分分布在较宽灰度范围但不均匀对比度较低。直方图覆盖整个灰度范围且分布均匀对比度高视觉效果较好。直方图均衡化必考直方图均衡化是最重要、最高频的考点。它的目标是把原始图像的直方图通过灰度变换调整为近似均匀分布从而提高图像对比度。核心步骤如下计算原始图像的灰度直方图得到各灰度级概率 p(r_k) n_k / (M×N)。计算累积分布函数CDFs_k (L - 1) * Σ_{j0}^{k} p(r_j)对 s_k 取整映射到新的灰度值。期末计算题常给一张 4×4 或 8×8 的小图让你手动计算均衡化后的灰度分布。只要按照上面步骤一步步写不太会出错。建议考前至少徒手做一遍。我在第 4 节会给出直方图均衡化的完整代码和手动推算示例。直方图匹配规定化与均衡化不同直方图匹配是希望变换后图像的直方图接近预先指定的形状。理解它和均衡化的区别即可考代码的概率低。3.3 空间滤波卷积的直观入门空间滤波是第二章的重点几乎必考。它的数学本质是“模板卷积”但你可以先把它理解成一个滑动窗口对像素邻域做加权平均。空间滤波表达式设图像 f 大小为 M×N滤波器模板 w 大小为 m×n通常 m、n 为奇数则在点 (x,y) 处的滤波结果为g(x,y) Σ_{s-a}^{a} Σ_{t-b}^{b} w(s,t) * f(xs, yt)其中 a(m-1)/2b(n-1)/2也就是模板中心对准正在处理的像素。平滑滤波均值模糊与高斯模糊均值滤波是取邻域内像素的均值作为输出主要用于模糊图像、降低噪声。高斯滤波是加权平均越靠近中心点的像素权重越大。3×3 高斯模板常见的近似形式为| 1 2 1 | 1/16 | 2 4 2 | | 1 2 1 |高斯滤波相比均值滤波能更好地保留边缘信息这也是 OpenCV 中GaussianBlur被广泛使用的原因。统计排序滤波中值滤波中值滤波的原理很简单把邻域内的像素灰度值排序取中间值作为结果。它对抗椒盐噪声效果特别好因为在排序后孤立的极值噪声会被“挤到两端”。考试常问“中值滤波适合去除什么噪声为什么”答案是椒盐噪声因为椒盐噪声是以黑白点的形式出现与邻域差异极大排序取中值后基本可以消除。锐化滤波拉普拉斯算子锐化滤波器用于突出图像的边缘和细节。拉普拉斯算子是最常用的二阶微分算子。常见的 3×3 拉普拉斯模板有两种形式| 0 -1 0 | | -1 -1 -1 | | -1 4 -1 | | -1 8 -1 | | 0 -1 0 | | -1 -1 -1 |如果直接把拉普拉斯结果叠加到原图可以实现锐化增强g(x,y) f(x,y) c * [∇² f(x,y)]其中若使用中心系数为正的模板c 通常取 1若使用中心系数为负的模板c 通常取 -1。空间滤波做题提示空间滤波题目经常给一个小矩阵和一个模板问你“该模板输出中心的像素值是多少”。这类题只要记得“模板中心对应待处理像素模板系数与图像对应位置相乘再求和”一般不会错。计算时注意模板边界是否需要补 0通常如果没有特殊说明默认不处理边界或补 0。3.4 频域滤波傅里叶变换的直观理解频域滤波是很多人的畏难点因为傅里叶变换的数学公式看起来不友好。但从考试角度看理解以下内容基本就够应付大部分题目了。二维离散傅里叶变换2D DFT二维离散傅里叶变换公式F(u,v) Σ_{x0}^{M-1} Σ_{y0}^{N-1} f(x,y) * e^(-j2π(ux/M vy/N))这个公式不需要你背得很痛苦但你要知道它做了什么把图像从空间域变换到频率域。低频对应图像中灰度变化缓慢的区域高频对应边缘、细节和噪声。频域滤波的基本步骤标准流程如下对输入图像做傅里叶变换F(u,v) DFT[f(x,y)]。将 F(u,v) 中心化把低频移到频谱中心。用滤波器函数 H(u,v) 乘以频谱G(u,v) H(u,v) · F(u,v)。对 G(u,v) 做傅里叶逆变换取实部得到滤波后图像。这个过程常出现在简答题或实验报告中要求你描述频域高通/低通滤波的处理流程。低通、高通、带通与带阻低通滤波器保留低频、抑制高频作用是平滑图像、去噪代价是边缘变模糊。高通滤波器保留高频、抑制低频作用是锐化边缘代价是丢失平坦区域信息。带通滤波器保留特定频带。带阻滤波器抑制特定频带常用于去除周期性噪声。常见的几种滤波器函数包括理想滤波器、巴特沃斯滤波器和高斯滤波器。其中理想滤波器由于在截止频率处突变会产生振铃效应高斯滤波器过渡平滑不会出现振铃。这个结论常考。3.5 图像复原与图像增强的爱恨纠葛图像复原与图像增强的目标看起来很像都是“改善图像质量”但两者有本质区别图像增强是主观过程目标是让图像“看起来更好”不追究图像为什么变差。图像复原是客观过程需要建立图像退化模型并根据退化原因进行逆操作。期末简答题如果问“图像增强与图像复原的区别”就按这个思路回答。图像退化模型图像退化模型可以写为g(x,y) h(x,y) * f(x,y) η(x,y)其中 h(x,y) 是退化函数点扩散函数η(x,y) 是加性噪声* 是卷积。图像复原的目标就是在已知 g 和 h、η 的情况下尽可能恢复 f。逆滤波与维纳滤波逆滤波直接用频域除法恢复公式为 F̂(u,v) G(u,v) / H(u,v)。但 H(u,v) 在零点附近很小噪声会被无限放大因此实际很少直接使用。维纳滤波在最小均方误差准则下兼顾去卷积与噪声抑制公式带有一个噪声相关的参数项对噪声有更好的鲁棒性。理解“逆滤波为什么不可行维纳滤波如何改进”这个逻辑链就能应对大多数图像复原简答题。常见噪声模型高斯噪声、椒盐噪声脉冲噪声、均匀噪声等名称和特点要能辨析。噪声参数估计和滤波选择也是考研选择题的常见素材。3.6 彩色图像处理会做通道拆分即可这一章在期末中占比通常不大重点是彩色模型。需要掌握RGB 模型用红绿蓝三通道表示颜色HSI 模型用色调、饱和度、强度表示颜色更符合人的视觉感知CMY/CMYK 用于打印灰度图转彩色是伪彩色处理。实验题常要求拆分 RGB 三通道并显示。这个用 OpenCV 做非常简单后面实战部分会演示。3.7 形态学图像处理结构元素去“修”二值图形态学处理通常以二值图像为对象核心操作有膨胀、腐蚀、开运算、闭运算。腐蚀与膨胀腐蚀是取结构元素覆盖区域内的最小值等价于“缩小”前景区域能去除小且细的噪声点。膨胀是取最大值等价于“扩大”前景区域能填补前景中的小孔。开运算与闭运算开运算 先腐蚀后膨胀作用是去除细小物体、分离相连物体。闭运算 先膨胀后腐蚀作用是填充小孔、连接邻近物体。这两个“先后顺序”很容易记混我提供一个记忆方法开运算的“开”是先腐蚀像把物体拆开闭运算的“闭”是先膨胀像把缺口闭合。公式记忆A ∘ B (A ⊖ B) ⊕ B // 开运算 A • B (A ⊕ B) ⊖ B // 闭运算其中 ⊕ 表示膨胀⊖ 表示腐蚀。3.8 图像分割从边缘到区域图像分割是期末和考研的重点模块公式不算多但算法概念非常多。边缘检测边缘是图像灰度发生剧烈变化的地方。常用算子有Roberts 算子计算对角线方向差分对噪声敏感。Prewitt 算子利用 3×3 模板做一阶微分。Sobel 算子结合平滑与微分的 3×3 模板是 Prewitt 的改进。Canny 算子最经典的边缘检测算法分多步完成高斯滤波去噪 → 计算梯度幅值和方向 → 非极大值抑制 → 双阈值检测和边缘连接。考试常让你写出 Sobel 的水平/垂直模板或者描述 Canny 边缘检测的步骤。后者一定会考务必背熟。阈值分割阈值分割是最简单的图像分割方法。全局阈值选取一个阈值 T将像素分为目标和背景。如果能通过直方图的波谷确定阈值称为峰谷法。Otsu 算法大津法是期末热点。它的思想是在 0~255 内遍历每个灰度级作为阈值计算目标与背景的类间方差取类间方差最大时的灰度值作为最优阈值。Otsu 的实现代码比较简单下面的实验实战部分会给出完整示例。考试可能会手动让你算两类的均值和概率然后求类间方差准备时应掌握公式σ_B² ω0 * ω1 * (μ0 - μ1)²其中 ω0、ω1 分别是目标和背景像素占比μ0、μ1 分别是目标与背景的平均灰度。区域分割区域生长、区域分裂合并是另一类分割方法。概念题为主需要理解“从种子点出发按相似性准则逐步扩展区域”的基本思想。4. 期末必会实验手把手带你写代码期末复习阶段如果能独立完成以下 4 个小实验你对这门课的理解会明显提升。每个实验我都给出可直接运行的代码建议在 Jupyter Notebook 或 PyCharm 里逐个跑一遍。4.1 实验一直方图均衡化直方图均衡化是最常考的实验OpenCV 中已经有了现成函数cv2.equalizeHist但为了理解原理我推荐先自己实现一遍再用现成函数验证。# 文件路径lab01_hist_equalization.py import cv2 import numpy as np import matplotlib.pyplot as plt # 1. 读取灰度图 img cv2.imread(test_image.png, cv2.IMREAD_GRAYSCALE) if img is None: print(请确认图片路径是否正确) exit() # 2. 手动实现直方图均衡化 def my_equalize_hist(image): h, w image.shape total h * w # 统计灰度直方图 hist np.zeros(256, dtypenp.float64) for i in range(h): for j in range(w): hist[image[i, j]] 1 # 计算累积分布函数并映射 lut np.zeros(256, dtypenp.uint8) accum 0.0 for k in range(256): accum hist[k] # L-1255 lut[k] int(255 * accum / total 0.5) # 进行灰度映射 result lut[image] return result # 3. 对比 OpenCV 自带的均衡化函数 manual_result my_equalize_hist(img) opencv_result cv2.equalizeHist(img) # 4. 绘制原图、结果图和直方图 plt.figure(figsize(12, 8)) plt.subplot(3, 2, 1) plt.imshow(img, cmapgray) plt.title(原始图像) plt.axis(off) plt.subplot(3, 2, 2) plt.imshow(manual_result, cmapgray) plt.title(手动均衡化结果) plt.axis(off) plt.subplot(3, 2, 3) plt.imshow(opencv_result, cmapgray) plt.title(OpenCV 均衡化结果) plt.axis(off) plt.subplot(3, 2, 4) plt.hist(img.ravel(), bins256, range[0, 256], colorblue, alpha0.7) plt.title(原始直方图) plt.subplot(3, 2, 5) plt.hist(manual_result.ravel(), bins256, range[0, 256], colorred, alpha0.7) plt.title(均衡化后直方图) plt.tight_layout() plt.show()运行这段代码你会明显看到输出图像的直方图分布比原来更平缓对比度更高。如果原图偏暗效果会更明显。这里需要注意边界像素的取值问题手动实现时如果累加值乘以 255 后取整应与 OpenCV 结果基本一致。若不完全相同通常是舍入方式差异造成的不影响理解。4.2 实验二空间滤波对比这个实验用来直观感受均值滤波、高斯滤波、中值滤波在不同噪声下的效果差异。重点是理解三种滤波器的适用场景。# 文件路径lab02_spatial_filter.py import cv2 import numpy as np import matplotlib.pyplot as plt # 读取图片并转为灰度 img cv2.imread(test_image.png, cv2.IMREAD_GRAYSCALE) if img is None: print(请确认图片路径是否正确) exit() # 添加高斯噪声 def add_gaussian_noise(image, mean0, sigma20): noise np.random.normal(mean, sigma, image.shape) noisy image noise return np.clip(noisy, 0, 255).astype(np.uint8) # 添加椒盐噪声 def add_salt_pepper_noise(image, prob0.05): noisy image.copy() h, w image.shape for i in range(h): for j in range(w): rand np.random.rand() if rand prob / 2: noisy[i, j] 0 elif rand prob: noisy[i, j] 255 return noisy gaussian_noisy add_gaussian_noise(img) sp_noisy add_salt_pepper_noise(img) # 各种滤波 mean_filtered_g cv2.blur(gaussian_noisy, (3, 3)) gaussian_filtered_g cv2.GaussianBlur(gaussian_noisy, (3, 3), 0) median_filtered_g cv2.medianBlur(gaussian_noisy, 3) mean_filtered_sp cv2.blur(sp_noisy, (3, 3)) gaussian_filtered_sp cv2.GaussianBlur(sp_noisy, (3, 3), 0) median_filtered_sp cv2.medianBlur(sp_noisy, 3) # 展示结果 plt.figure(figsize(12, 9)) plt.subplot(3, 3, 1) plt.imshow(gaussian_noisy, cmapgray) plt.title(高斯噪声图) plt.axis(off) plt.subplot(3, 3, 2) plt.imshow(mean_filtered_g, cmapgray) plt.title(均值滤波 - 高斯噪声) plt.axis(off) plt.subplot(3, 3, 3) plt.imshow(gaussian_filtered_g, cmapgray) plt.title(高斯滤波 - 高斯噪声) plt.axis(off) plt.subplot(3, 3, 4) plt.imshow(median_filtered_g, cmapgray) plt.title(中值滤波 - 高斯噪声) plt.axis(off) plt.subplot(3, 3, 5) plt.imshow(sp_noisy, cmapgray) plt.title(椒盐噪声图) plt.axis(off) plt.subplot(3, 3, 6) plt.imshow(mean_filtered_sp, cmapgray) plt.title(均值滤波 - 椒盐噪声) plt.axis(off) plt.subplot(3, 3, 7) plt.imshow(gaussian_filtered_sp, cmapgray) plt.title(高斯滤波 - 椒盐噪声) plt.axis(off) plt.subplot(3, 3, 8) plt.imshow(median_filtered_sp, cmapgray) plt.title(中值滤波 - 椒盐噪声) plt.axis(off) plt.subplot(3, 3, 9) plt.imshow(cv2.medianBlur(sp_noisy, 5), cmapgray) plt.title(中值滤波(5x5) - 椒盐噪声) plt.axis(off) plt.tight_layout() plt.show()运行结果会告诉你一个重要结论去除椒盐噪声时中值滤波效果最好去除高斯噪声时高斯滤波效果优于均值滤波均值滤波会把边缘变得模糊而中值滤波在去除椒盐噪声时细节保持相对更好。4.3 实验三Canny 边缘检测Canny 边缘检测需要先知道两个核心参数threshold1和threshold2。threshold2用于检测强边缘threshold1用于连接弱边缘。实际应用中这两个值通常按 1:2 或 1:3 的比例设置。# 文件路径lab03_canny_edge.py import cv2 import numpy as np import matplotlib.pyplot as plt img cv2.imread(test_image.png, cv2.IMREAD_GRAYSCALE) if img is None: print(请确认图片路径是否正确) exit() # 使用 Canny 边缘检测 edges1 cv2.Canny(img, 50, 150) edges2 cv2.Canny(img, 100, 200) edges3 cv2.Canny(img, 30, 100) # 对比不同阈值的影响 plt.figure(figsize(12, 4)) plt.subplot(1, 4, 1) plt.imshow(img, cmapgray) plt.title(原始图像) plt.axis(off) plt.subplot(1, 4, 2) plt.imshow(edges1, cmapgray) plt.title(Canny(50, 150)) plt.axis(off) plt.subplot(1, 4, 3) plt.imshow(edges2, cmapgray) plt.title(Canny(100, 200)) plt.axis(off) plt.subplot(1, 4, 4) plt.imshow(edges3, cmapgray) plt.title(Canny(30, 100)) plt.axis(off) plt.tight_layout() plt.show() print(Canny 边缘检测完成)观察输出可以发现阈值设置越高检测出的边缘越少但留下的边缘通常更清晰阈值设置越低细小边缘和噪声点也会被当作边缘检测出来。考场上如果让你描述 Canny 算法的步骤记住五个阶段即可高斯滤波平滑图像减少噪声计算梯度幅值和方向通常用 Sobel 算子对梯度幅值做非极大值抑制双阈值检测将像素分为强边缘、弱边缘和非边缘通过滞后连接将弱边缘与强边缘连接的像素保留。4.4 实验四Otsu 自适应阈值分割Otsu 算法是图像分割中最重要的自适应阈值方法不需要人为指定阈值算法自动寻找类间方差最大的灰度值。# 文件路径lab04_otsu.py import cv2 import numpy as np import matplotlib.pyplot as plt img cv2.imread(test_image.png, cv2.IMREAD_GRAYSCALE) if img is None: print(请确认图片路径是否正确) exit() # 手动实现 Otsu def my_otsu(image): hist cv2.calcHist([image], [0], None, [256], [0, 256]).ravel() hist hist / image.size # 归一化为概率 best_thresh 0 best_var 0.0 for t in range(256): # 背景类0 ~ t w0 hist[:t1].sum() # 目标类t1 ~ 255 w1 hist[t1:].sum() if w0 0 or w1 0: continue # 均值计算 mu0 np.sum(np.arange(0, t1) * hist[:t1]) / w0 mu1 np.sum(np.arange(t1, 256) * hist[t1:]) / w1 # 类间方差 var_between w0 * w1 * (mu0 - mu1) ** 2 if var_between best_var: best_var var_between best_thresh t return best_thresh # 计算阈值 my_thresh my_otsu(img) _, cv_thresh_result cv2.threshold(img, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU) _, my_thresh_result cv2.threshold(img, my_thresh, 255, cv2.THRESH_BINARY) print(手动 Otsu 阈值, my_thresh) print(OpenCV Otsu 阈值, cv_thresh_result) # 可视化 plt.figure(figsize(12, 4)) plt.subplot(1, 3, 1) plt.imshow(img, cmapgray) plt.title(原始图像) plt.axis(off) plt.subplot(1, 3, 2) plt.imshow(cv_thresh_result, cmapgray) plt.title(OpenCV Otsu 分割) plt.axis(off) plt.subplot(1, 3, 3) plt.imshow(my_thresh_result, cmapgray) plt.title(f手动 Otsu 分割 (T{my_thresh})) plt.axis(off) plt.tight_layout() plt.show()手动实现的 Otsu 遍历了 0 到 255 每一个灰度级计算每个阈值对应的类间方差。类间方差越大说明前景背景分离得越彻底。实际工程中用cv2.threshold(img, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU)一行代码即可完成但了解底层计算逻辑在考试中更重要。4.5 综合练习图像增强与分割的流水线如果上面 4 个实验都能独立完成可以试着把多个知识点串成一个完整任务# 文件路径lab05_enhance_and_segment.py 任务对一张含噪图像完成以下流程 1. 添加椒盐噪声 2. 使用中值滤波去噪 3. 使用直方图均衡化增强对比度 4. 使用 Otsu 方法分割出主要物体。 import cv2 import numpy as np import matplotlib.pyplot as plt np.random.seed(42) # 生成原始图像模拟前景与背景 img np.zeros((256, 256), dtypenp.uint8) cv2.circle(img, (128, 128), 60, 200, -1) cv2.rectangle(img, (30, 30), (90, 90), 120, -1) # 添加椒盐噪声 def add_salt_pepper_noise(image, prob0.05): noisy image.copy() h, w image.shape mask np.random.rand(h, w) noisy[mask prob / 2] 0 noisy[mask 1 - prob / 2] 255 return noisy noisy_img add_salt_pepper_noise(img) # 中值滤波去噪 denoised cv2.medianBlur(noisy_img, 5) # 直方图均衡化增强 enhanced cv2.equalizeHist(denoised) # Otsu 分割 _, segmented cv2.threshold(enhanced, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU) # 绘制结果 plt.figure(figsize(12, 4)) plt.subplot(1, 4, 1) plt.imshow(img, cmapgray) plt.title(原始图像) plt.axis(off) plt.subplot(1, 4, 2) plt.imshow(noisy_img, cmapgray) plt.title(添加椒盐噪声) plt.axis(off) plt.subplot(1, 4, 3) plt.imshow(enhanced, cmapgray) plt.title(中值滤波 均衡化) plt.axis(off) plt.subplot(1, 4, 4) plt.imshow(segmented, cmapgray) plt.title(Otsu 分割结果) plt.axis(off) plt.tight_layout() plt.show()对简单的二值图来说中值滤波去噪效果非常明显均衡化可以增强微弱区域Otsu 能自动将物体从背景中分离出来。这套流水线也是很多图像预处理任务的基础流程。5. 考研与期末的区别复习侧重点提示5.1 期末重计算考研重原理如果是准备合肥学院的期末考试我的建议是课后习题一定要自己动手算。尤其是直方图均衡化的手算过程、空间滤波的模板计算、距离度量计算这些题目只要练熟了就是送分题。如果是准备考研题目往往更侧重“算法设计思想”和“方法对比分析”。比如为什么频域滤波会出现振铃效应图像复原与图像增强在目标和方法上有什么区别中值滤波为什么会破坏图像的细线结构与一阶微分算子相比拉普拉斯算子对噪声更敏感的原因是什么这些问题不是背诵能解决的需要你在平时的实验中去观察现象、思考原因。比如你在实验二里实际跑过中值滤波就会注意到它虽然能去椒盐噪声但图像中细小的线状结构会因为排序操作被“抹平”这就是中值滤波的局限性。5.2 图像处理“2026 年新应用”热点的理解复习时如果还有余力可以稍微关注一下数字图像处理在医学影像、自动驾驶、工业检测、遥感图像分析中的最新应用。复试中老师可能通过“你知道数字图像处理目前有哪些新应用”这类问题来考察你对学科前沿的兴趣。目前比较常见的方向包括医学影像中的图像分割与病灶检测自动驾驶场景下的道路分割与目标检测工业质检中的表面缺陷检测手机摄影中的超分辨率与 HDR 合成遥感图像中的地物分类与变化检测。值得强调的是传统数字图像处理仍然是这些应用的基础。深度学习解决的是“特征自动提取”的问题但数据预处理、边缘检测、形态学后处理仍然大量依赖你在本科学到的经典图像处理方法。6. 实验与代码常见问题排查6.1 OpenCV 读取图片后显示一片空白现象用 matplotlib 显示 cv2.imread 读取的“彩色图”时颜色完全不对例如红蓝颠倒。原因OpenCV 默认使用 BGR 通道顺序而 matplotlib 使用 RGB 顺序。如果直接读取彩色图并用 matplotlib 展示就会出现通道顺序错乱。解决把 BGR 转为 RGB 再显示。img_bgr cv2.imread(image.jpg) img_rgb cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)6.2 图片路径包含中文导致读取失败现象cv2.imread返回 None。原因OpenCV 的 imread 函数对中文路径支持不友好。解决先使用imdecode方式读取。import cv2 import numpy as np def cv_imread(file_path): 解决 OpenCV 读取中文路径返回 None 的问题 data np.fromfile(file_path, dtypenp.uint8) img cv2.imdecode(data, cv2.IMREAD_COLOR) if img is None: img cv2.imdecode(data, cv2.IMREAD_GRAYSCALE) return img6.3 灰度图显示为绿色或伪彩色现象plt.imshow(img, cmapgray)后发现显示的是绿色图像。原因matplotlib 在使用 imshow 时如果没有指定 vmin 和 vmax可能自动调整显示范围。此外如果传入的数组维度不是二维而是三通道cmap 参数不生效。解决确认传入的是二维数组必要时打印 img.shape 查看维度。print(img.shape)如果是(height, width, 3)需要先转成灰度。gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)6.4 手动实现 Otsu 与 OpenCV 结果不一致现象自己写的 Otsu 阈值和cv2.threshold的 Otsu 阈值略有出入。原因OpenCV 内部的阈值计算可能使用了不同的等号判定或浮点数精度处理。解决如果你的训练结果和 OpenCV 相差 1 个灰度级以内通常属于正常范围不需要过度纠结。重点是理解类间方差最大化的思想。6.5 Canny 边缘检测出现大量短线噪声现象边缘图中除了目标边缘还有大量杂乱短线。原因阈值设置过低或者原图噪声没有去除完全。解决先做一次高斯滤波再调大 Canny 阈值。blurred cv2.GaussianBlur(img, (5, 5), 0) edges cv2.Canny(blurred, 80, 200)7. 期末高频考点自查表与复习策略7.1 高频考点一览下面这张表是我的建议复习清单你可以逐条打勾章节高频考点掌握程度图像数字化采样与量化概念、存储容量计算、像素间距离必会灰度变换对数/幂次变换选择、图像反转变换必会直方图直方图含义、均衡化手算步骤必会空间滤波卷积计算、均值/中值/高斯选择、拉普拉斯锐化必会频域滤波DFT 流程、低通/高通/带阻作用、振铃效应重点图像复原退化模型、逆滤波缺陷、维纳滤波思想重点彩色图像RGB/HSI 模型、伪彩色处理了解形态学腐蚀/膨胀、开/闭运算必会图像分割梯度算子、Canny 步骤、Otsu 思想、区域生长必会图像压缩/编码如有冗余概念、无损/有损压缩、JPEG 原理了解7.2 考前两周怎么复习效率最高这里分享一个比较实用的三轮复习法适合完整跟完课程但还没系统复习的同学第一轮3~4 天按章节过教材和课件只梳理概念、公式和框图。遇到看不懂的公式先跳过不恋战。第二轮5~7 天专攻计算题和代码题。把直方图均衡化、空间滤波、边缘检测、Otsu 这些典型题目用手算一遍再用代码验证一遍。考研的同学这个阶段需要补充推导能力。第三轮2~3 天集中背诵概念性考点包括各种算法的优点缺点、算子之间的区别、图像增强与复原的差异等。同时把自己的实验报告拿出来重新过一遍尤其是老师实验课上强调过的结论。三轮结束以后如果还有时间可以做 1~2 套往年试卷或课后重点题。不要盲目刷题这门课更注重“算法思想是否梳理得清楚”。7.3 考场上的注意细节期末考场上图像处理的计算题很容易因为符号写错而丢分。这里给你几个提醒均衡化计算时累积概率乘以 (L-1) 后要取整不要四舍五入到 256 或 0 之外。卷积计算时先把模板旋转 180° 再滑动相乘才是严格意义上的卷积。不过因为大多数模板是对称的这一步通常被省略但如果模板不对称要留意题目考查的是“卷积”还是“相关”。写简答题时先写定义再写公式最后写优缺点或适用场景。分点回答更容易拿全分。拉普拉斯模板不是唯一的不同教材中心系数可能是 4 或 8做题前先看模板。7.4 考研党的后续学习建议如果你是为了考研复试准备这门课建议在期末复习之后再往前多看一步读冈萨雷斯教材的英文版术语因为复试时老师可能会直接说英文术语例如 spatial filtering、histogram equalization、morphological processing。了解 OpenCV 官方文档中的基本 API面试时如果涉及项目你至少能说清楚图像处理代码的基本流程。找一个你感兴趣的小项目做透比堆砌十个简单实验更有价值。例如“手机拍照文档去阴影”“票据关键区域定位”一个完整项目可以同时覆盖预处理、分割、形态学、特征提取等多个知识模块。复试被问到本科实验时最忌讳的回答是“老师让我们做我就照着做了”。如果你能说清楚每个步骤的目的、参数调整的依据、遇到问题后如何排查面试官就会认为你真正掌握这门课。8. 写在最后数字图像处理是“越学越有用”的课《数字图像处理》看起来是一门偏理论的课程但它的每个知识点都对应实际场景手机拍照去噪靠的是空间滤波医学影像增强靠的是直方图处理工业零件检测靠的是边缘检测与形态学自动文档扫描靠的是阈值分割与透视校正。如果这学期你只是跟班听了一遍现在正好通过复习把碎片知识串起来。建议你打开电脑把上面的实验代码逐个运行一遍边跑边在纸上画一画每个算法到底做了什么你会发现这门课程远没有想象中那么难。本文的代码你可以直接复制到本机运行实验图片换成自己的一张普通照片也能观察效果。对于更复杂的方向例如深度学习图像分割、生成对抗网络图像修复也建议在打好经典图像处理基础后再去接触那时你会更快上手也更加明白经典方法的价值所在。如果这篇文章对你的期末复习或考研准备有帮助收藏备用即可。祝你在《数字图像处理》考试中拿到满意成绩。
返回列表