纲要¶

图像滤波¶

空间域滤波¶

空间域滤波是直接对图像的像素进行处理,根据滤波器的作用不同,又可分为线性滤波和非线性滤波。

线性滤波¶

  • 均值滤波
    • 原理:用滤波器模板确定的邻域内像素的平均灰度值去代替图像每个像素点的值,即对邻域内的像素进行简单的算术平均。
    • 特点:算法简单,计算速度快,但会导致图像边缘模糊,因为它对所有像素一视同仁,没有考虑到像素之间的差异。
    • 应用场景:常用于去除图像中的高斯噪声,对图像进行平滑处理。
  • 高斯滤波
    • 原理:根据高斯函数的形状来选择权值,对邻域内的像素进行加权平均。离中心点越近的像素,其权重越大,离中心点越远的像素,其权重越小。
    • 特点:能够有效地平滑图像,同时保留图像的边缘信息,因为它对不同位置的像素赋予了不同的权重,更加符合人眼的视觉特性。
    • 应用场景:广泛应用于图像去噪、图像预处理等领域,特别是在需要保留图像边缘的情况下。

非线性滤波¶

  • 中值滤波
    • 原理:将滤波器模板确定的邻域内的像素值进行排序,取中间值作为当前像素点的输出值。
    • 特点:对脉冲噪声(椒盐噪声)有很好的抑制作用,能够在去除噪声的同时,较好地保留图像的边缘和细节信息,因为它只考虑像素值的大小关系,而不涉及像素值的加减运算。
    • 应用场景:常用于处理受椒盐噪声污染的图像,如医学图像、遥感图像等。
  • 双边滤波
    • 原理:结合了图像的空间邻近度和像素值相似度,在滤波过程中,不仅考虑了像素的空间位置关系,还考虑了像素值之间的差异。对于空间上相近且像素值相似的像素,赋予较大的权重;对于空间上较远或像素值差异较大的像素,赋予较小的权重。
    • 特点:能够在去噪的同时,更好地保留图像的边缘和纹理信息,因为它综合考虑了空间和像素值两个因素。
    • 应用场景:适用于对图像质量要求较高的场合,如人像美颜、图像增强等。

频率域滤波¶

频率域滤波是先将图像从空间域转换到频率域,在频率域中对图像的频率成分进行处理,然后再将处理后的图像转换回空间域。常用的频率域滤波方法包括低通滤波、高通滤波、带通滤波和带阻滤波等。

  • 低通滤波
    • 原理:允许低频信号通过,而抑制高频信号。在图像处理中,图像的低频部分对应着图像的平滑区域,高频部分对应着图像的边缘和噪声。因此,低通滤波可以用于图像的平滑处理,去除图像中的高频噪声。
    • 常见方法:理想低通滤波器、巴特沃斯低通滤波器、高斯低通滤波器等。
    • 应用场景:常用于图像去噪、图像模糊处理等。
  • 高通滤波
    • 原理:允许高频信号通过,而抑制低频信号。在图像处理中,高通滤波可以增强图像的边缘和细节信息,使图像更加清晰。
    • 常见方法:理想高通滤波器、巴特沃斯高通滤波器、高斯高通滤波器等。
    • 应用场景:常用于图像锐化、边缘检测等。
  • 带通滤波和带阻滤波
    • 原理:带通滤波器允许某一频带内的信号通过,而抑制该频带以外的信号;带阻滤波器则抑制某一频带内的信号,而允许该频带以外的信号通过。
    • 应用场景:在图像处理中,带通滤波和带阻滤波的应用相对较少,但在某些特定的图像处理任务中可能会用到,例如去除图像中特定频率的干扰信号。

边缘检测¶

一阶微分边缘检测算子¶

  • Sobel算子
    • 原理:Sobel算子是一种离散微分算子,它结合了高斯平滑和微分求导。该算子包含两组3×3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。
    • 特点:计算简单,对噪声有一定的平滑作用,能够提供较为精确的边缘方向信息。但它对边缘的定位精度相对不高,检测出的边缘可能会比较粗。
    • 应用场景:常用于对实时性要求较高且对边缘精度要求不是特别严格的场景,如一些简单的目标检测、图像分割等任务。
  • Prewitt算子
    • 原理:Prewitt算子也是一种基于一阶微分的边缘检测算子,它同样利用像素点上下、左右邻点的灰度差,在边缘处达到极值检测边缘。与Sobel算子类似,它也有水平和垂直两个方向的模板。
    • 特点:对噪声相对敏感,边缘检测效果与Sobel算子相近,但在某些情况下,对边缘的响应可能会稍弱一些。
    • 应用场景:适用于图像噪声相对较小,且对边缘检测速度有一定要求的场景,例如在一些工业检测中对简单形状物体的边缘提取。
  • Roberts算子
    • 原理:Roberts算子是一种最简单的算子,它采用对角线方向相邻两像素之差近似梯度幅值来检测边缘。利用局部差分算子寻找边缘,通过计算2×2邻域内的对角线方向像素值之差来近似梯度幅值。
    • 特点:定位精度较高,但对噪声非常敏感,容易检测出伪边缘。由于其检测的边缘比较细,适合检测具有陡峭边缘且噪声较小的图像。
    • 应用场景:常用于对边缘细节要求较高、图像噪声较小的场景,如一些医学图像中特定组织的边缘检测。

二阶微分边缘检测算子¶

  • Laplacian算子
    • 原理:Laplacian算子是一种二阶微分算子,它具有各向同性,即与坐标轴方向无关,坐标轴旋转后梯度结果不变。通过对图像进行二阶微分运算,根据二阶导数的过零点来确定边缘的位置。
    • 特点:对噪声非常敏感,会增强图像中的噪声。但它能够检测出图像中的孤立点、线端和细线等细节,边缘定位精度较高。
    • 应用场景:通常需要先对图像进行平滑处理以减少噪声的影响,然后再使用Laplacian算子进行边缘检测,适用于一些对边缘细节要求较高且图像噪声相对容易控制的场景。
  • LoG(Laplacian of Gaussian)算子
    • 原理:LoG算子是Laplacian算子和高斯滤波器的结合。先使用高斯滤波器对图像进行平滑处理,以抑制噪声,然后再使用Laplacian算子进行边缘检测。这样可以在一定程度上克服Laplacian算子对噪声敏感的缺点。
    • 特点:能够有效地检测边缘,同时对噪声有一定的抑制作用。但它计算量相对较大,因为需要进行高斯滤波和二阶微分运算。
    • 应用场景:广泛应用于图像分割、特征提取等领域,特别是在对图像质量和边缘检测精度要求较高的情况下。

Canny边缘检测算子¶

  • 原理:Canny边缘检测算子是一个多阶段算法,主要包括以下几个步骤:
    1. 高斯滤波:对图像进行高斯平滑滤波,以减少噪声的影响。
    2. 计算梯度幅值和方向:使用一阶微分算子(如Sobel算子)计算图像中每个像素点的梯度幅值和方向。
    3. 非极大值抑制:对梯度幅值图像进行非极大值抑制,以细化边缘,只保留局部梯度幅值最大的点作为候选边缘点。
    4. 双阈值检测和边缘连接:设置两个阈值(高阈值和低阈值),将梯度幅值大于高阈值的像素点标记为强边缘点,梯度幅值介于高阈值和低阈值之间的像素点标记为弱边缘点,梯度幅值小于低阈值的像素点则被抑制。然后通过连接强边缘点和与之相连的弱边缘点来形成最终的边缘。
  • 特点:具有低错误率、高定位精度和单一边缘响应等优点。能够有效地检测出图像中的真实边缘,同时抑制虚假边缘的产生。
  • 应用场景:是目前应用最为广泛的边缘检测算法之一,适用于各种复杂的图像场景,如目标识别、图像匹配、自动驾驶中的环境感知等。

图像增强¶

空间域增强¶

空间域增强是直接对图像的像素灰度值进行操作,主要包括灰度变换和空间滤波。

灰度变换¶

  • 线性灰度变换
    • 原理:通过线性函数对图像的灰度值进行拉伸或压缩。公式为(g(x,y)=a\times f(x,y)+b),其中(f(x,y))是输入图像在点((x,y))处的灰度值,(g(x,y))是输出图像在点((x,y))处的灰度值,(a)和(b)是常数。
    • 特点:当(a > 1)时,图像对比度增强;当(0 < a < 1)时,图像对比度降低;(b)用于调整图像的整体亮度。
    • 应用场景:适用于图像整体灰度范围较窄,需要扩展灰度范围以提高对比度的情况,如一些曝光不足或过度的图像处理。
  • 非线性灰度变换
    • 对数变换:公式为(g(x,y)=c\times\log(1 + f(x,y))),其中(c)是常数。对数变换可以压缩图像的动态范围,增强图像中暗区域的细节,常用于处理动态范围很大的图像,如傅里叶频谱图。
    • 幂律(伽马)变换:公式为(g(x,y)=c\times f(x,y)^{\gamma}),其中(c)和(\gamma)是正常数。当(\gamma > 1)时,图像的高灰度区域得到扩展,低灰度区域被压缩;当(\gamma < 1)时,情况相反。幂律变换可用于图像的校正,如显示器或打印机的伽马校正。

空间滤波¶

  • 平滑滤波
    • 均值滤波:用滤波器模板确定的邻域内像素的平均灰度值去代替图像每个像素点的值。算法简单,计算速度快,但会导致图像边缘模糊,常用于去除图像中的高斯噪声。
    • 中值滤波:将滤波器模板确定的邻域内的像素值进行排序,取中间值作为当前像素点的输出值。对脉冲噪声(椒盐噪声)有很好的抑制作用,能在去噪的同时较好地保留图像的边缘和细节信息。
  • 锐化滤波
    • 拉普拉斯算子:是一种二阶微分算子,通过计算图像的二阶导数来检测边缘。对噪声敏感,会增强图像中的噪声,但边缘定位精度较高,常与其他方法结合使用来增强图像边缘。
    • 非锐化掩蔽:先对原图像进行模糊处理得到模糊图像,然后用原图像减去模糊图像得到掩蔽图像,最后将掩蔽图像按一定比例加到原图像上,从而增强图像的边缘和细节。

频率域增强¶

频率域增强是将图像从空间域转换到频率域,在频率域中对图像的频率成分进行处理,然后再转换回空间域。

  • 低通滤波
    • 理想低通滤波器:在频率域中,以截止频率为半径的圆内,所有频率分量无衰减地通过,圆外的频率分量完全被滤除。但会产生“振铃”效应,即在图像的边缘附近出现明显的振荡。
    • 巴特沃斯低通滤波器:其特性是连续衰减的,没有明显的截止频率。随着频率的增加,滤波器的响应逐渐减小,过渡比较平滑,能有效减少“振铃”效应。
    • 高斯低通滤波器:其频率响应呈高斯分布,能够平滑图像,同时较好地保留图像的边缘信息,在图像去噪和模糊处理中应用广泛。
  • 高通滤波
    • 理想高通滤波器:与理想低通滤波器相反,在截止频率为半径的圆内,所有频率分量被滤除,圆外的频率分量无衰减地通过。同样会产生“振铃”效应,可用于图像锐化,增强图像的高频成分,即边缘和细节。
    • 巴特沃斯高通滤波器:过渡特性平滑,能有效抑制“振铃”效应,在增强图像边缘的同时,保持图像的相对平滑。
    • 高斯高通滤波器:能够增强图像的高频信息,使图像的边缘更加清晰,同时对噪声有一定的抑制作用。

彩色图像增强¶

彩色图像增强不仅要考虑图像的亮度信息,还要考虑颜色信息,常见的方法有真彩色增强和假彩色增强。

  • 真彩色增强:直接对彩色图像的三个颜色分量(如RGB颜色空间的R、G、B分量)分别进行灰度图像增强的处理,然后再将处理后的三个分量合成彩色图像。这种方法简单直接,但可能会改变图像的颜色平衡。
  • 假彩色增强:将一幅彩色图像或多光谱图像的颜色映射到另一幅彩色图像的颜色空间中,以突出某些特定的信息。例如,将红外图像与可见光图像进行假彩色合成,可以突出目标与背景的差异,便于目标识别。

基于深度学习的图像增强¶

随着深度学习技术的发展,基于深度学习的图像增强方法取得了显著的成果。

  • 卷积神经网络(CNN)
    • 原理:通过多层卷积层、池化层和全连接层的组合,自动学习图像的特征表示。在图像增强中,可以训练一个CNN模型,将低质量的图像作为输入,高质量的图像作为输出,让模型学习从低质量图像到高质量图像的映射关系。
    • 特点:能够自动提取图像的高级特征,对各种复杂的图像退化情况有较好的适应性,但需要大量的标注数据进行训练。
    • 应用场景:广泛应用于图像去噪、超分辨率重建、图像去模糊等任务。
  • 生成对抗网络(GAN)
    • 原理:GAN由生成器和判别器组成。生成器负责生成逼真的图像,判别器负责判断输入的图像是真实图像还是生成器生成的图像。通过生成器和判别器之间的对抗训练,不断提高生成器生成图像的质量。
    • 特点:能够生成高质量、多样化的图像,在图像增强中可以生成更加自然、真实的增强结果。但训练过程相对复杂,容易出现模式崩溃等问题。
    • 应用场景:常用于图像风格迁移、图像修复、图像超分辨率重建等对图像质量要求较高的任务。

图像复原¶

基于退化模型估计的方法¶

  • 逆滤波复原:
    通过傅里叶变换将图像转换到频域,利用公式$F^\prime(u,v) = G(u,v)/H(u,v)$(其中$G(u,v)$为退化图像频域表示,$H(u,v)$为退化函数)直接求解原始图像估计值。但该方法在$H(u,v)$接近零时可能失效,且对噪声敏感,需在分母中加入常数或限制滤波频率以改进。

  • 维纳滤波复原:
    基于最小均方误差准则,利用噪声和图像的统计信息恢复图像。其传递函数为$H(u,v)=\frac{H^*(u,v)P_f(u,v)}{|H(u,v)|^2P_f(u,v)+P_n(u,v)}$,其中$P_f(u,v)$和$P_n(u,v)$分别为图像和噪声的功率谱。该方法可自动抑制噪声放大,但需较多先验知识。

  • 有约束最小二乘复原:
    在约束条件下寻找使准则函数最小的复原图像,通常采用平滑约束(如使原始图像的二阶导数平方和最小)。通过拉格朗日乘数法求解,适用于噪声统计特性未知的情况。

基于迭代运算的方法¶

  • Lucy-Richardson(L-R)复原:
    基于贝叶斯理论,假设退化图像、原始图像和点扩散函数服从泊松统计模型,通过迭代运算收敛于最大似然解。迭代公式为$f^{(n+1)}(x,y)=f^{(n)}(x,y)\left[\frac{h*(-g/h*f^{(n)})}{h*(-1+g/h*f^{(n)})}\right]$,适用于点扩散函数已知的情况。

基于退化图像先验信息的方法¶

  • 盲解卷积复原:
    在缺乏退化图像先验知识的情况下,通过迭代算法同时估计原始图像和点扩散函数。例如,使用deconvblind函数(如MATLAB中)进行复原,适用于无法准确获取退化模型参数的场景。

基于空间域和频率域处理的方法¶

  • 空间滤波复原:
    针对噪声存在的情况,采用均值滤波器(如算术均值、几何均值、谐波均值、逆谐波均值滤波器)或自适应滤波器(如自适应中值滤波器)进行去噪和复原。

  • 频率域滤波复原:
    通过傅里叶变换将图像转换到频域,利用带阻滤波器、带通滤波器或陷波滤波器消除噪声或特定频率分量。例如,使用n阶巴特沃思带阻滤波器或高斯带阻滤波器进行周期噪声的削减。

基于物理模型和统计模型的方法¶

  • 物理模型复原:
    基于光学和成像系统的物理原理(如反射、折射、衍射),模拟图像形成过程和退化现象,设计反卷积算法以重建清晰图像。例如,通过模拟运动模糊来设计反卷积算法。

  • 统计模型复原:
    基于图像数据的概率分布和统计特性(如噪声模型、图像纹理模型、统计相关性),从数据层面理解和解释图像特性。例如,利用Wiener滤波进行基于噪声统计特性的去噪。

图像重建¶

基于物理模型的重建¶

  • CT重建技术:
    • 滤波反投影(FBP):作为商用CT扫描仪最常用的分析重建方法,通过在投影数据上使用1D滤波器,将数据反投影到图像空间。其优势在于计算效率高且数值稳定性强,适用于不同世代的CT数据采集几何形状。
    • 迭代重建(IR):通过迭代优化数据保真项和保边正则化项的客观函数,在图像空间和投影空间之间进行正向与反向投影。相比FBP技术,迭代重建能更准确地纳入焦点和探测器几何形状、光子统计等物理因素,从而降低图像噪声、提高空间分辨率并减少伪影。

基于深度学习的重建¶

  • 深度学习重建:通过深度神经网络学习图像的高级特征,实现高质量的图像重建。常见的模型包括自编码器和生成对抗网络(GAN)。例如,2025年AI图像重建系统通过将传统多步迭代采样过程整合为单次推理网络,直接优化图像重建目标,显著提升了推理速度和重建质量。

基于数学变换的重建¶

  • 傅里叶变换重建:将图像转换为频域表示,通过频域处理和滤波后再进行逆傅里叶变换,实现图像重建。例如,低通滤波可用于去除图像中的高频噪声,从而恢复出清晰的图像。

基于插值的重建¶

  • 插值法:通过已知像素信息估计未知像素值,常见的插值方法包括最近邻插值、双线性插值和双三次插值。这些方法简单易用,适用于对计算复杂度要求较低的场景。

基于压缩感知的重建¶

  • 压缩感知重建:通过在采样阶段对图像进行稀疏表示,并利用稀疏性在重建阶段恢复图像。该方法在图像压缩和重建方面取得了显著效果,尤其适用于采样资源受限的场景。

基于多视角的三维重建¶

  • 单目与多目图像重建:
    • 单目图像重建:通过单个视角的二维图像估计三维场景,通常需要时间序列上的多幅图像。例如,运动恢复结构(SFM)技术可根据连续图像重建三维环境。
    • 多目图像重建:利用多个视角的图像数据,通过特征提取、匹配与建模,恢复三维场景。例如,立体视觉重建通过双目成像模型提取物体的三维信息,广泛应用于工业自动化和机器人领域。

基于模型的正则化重建¶

  • 基于模型的重建:利用先验知识和数学模型约束图像重建过程。例如,使用正则化方法(如TV正则化、稀疏表示正则化)对图像进行约束,以获得更准确的重建结果。

形态学图像处理¶


一、基本形态学操作¶

1. 腐蚀(Erosion)¶

  • 原理:用结构元素扫描图像的每个像素,将结构元素覆盖下的最小像素值作为输出图像对应位置的像素值。
  • 效果:
    • 缩小或细化图像中的物体。
    • 消除小的噪声点或孤立像素。
    • 分离两个或多个接触的物体。
  • 示例:若结构元素为3×3的方形,腐蚀操作会“腐蚀”掉图像边缘的像素,使物体变薄。

2. 膨胀(Dilation)¶

  • 原理:用结构元素扫描图像的每个像素,将结构元素覆盖下的最大像素值作为输出图像对应位置的像素值。
  • 效果:
    • 扩大或加粗图像中的物体。
    • 填充物体内部的小孔或断裂。
    • 连接相邻的物体。
  • 示例:膨胀操作会使图像中的物体变厚,填补物体内部的微小空洞。

二、组合形态学操作¶

1. 开运算(Opening)¶

  • 定义:先腐蚀后膨胀。
  • 效果:
    • 消除小物体。
    • 平滑较大物体的边界,同时不明显改变其面积。
    • 用于去除图像中的噪声或小颗粒。
  • 示例:在指纹图像中,开运算可以去除指纹纹路之间的细小噪点。

2. 闭运算(Closing)¶

  • 定义:先膨胀后腐蚀。
  • 效果:
    • 填充物体内部的小孔。
    • 连接邻近的物体。
    • 平滑边界,同时不明显改变其面积。
  • 示例:在印刷字符图像中,闭运算可以填充字符内部的微小断裂。

3. 击中击不中变换(HMT)¶

  • 原理:使用两个结构元素(一个匹配前景,一个匹配背景)来检测特定形状的物体。
  • 效果:
    • 精确提取图像中特定形状的物体。
    • 适用于形状匹配和定位。
  • 示例:在细胞图像中,HMT可以用于检测特定大小和形状的细胞。

4. 形态学梯度(Morphological Gradient)¶

  • 定义:膨胀图减去腐蚀图。
  • 效果:
    • 突出图像的边缘。
    • 增强图像中的细节。
  • 示例:在医学图像中,形态学梯度可以用于增强肿瘤的边缘。

5. 顶帽变换(Top-hat)¶

  • 定义:原图减去开运算结果。
  • 效果:
    • 提取图像中的亮细节。
    • 用于增强图像中的亮点或小物体。
  • 示例:在天文图像中,顶帽变换可以用于增强微弱的星体。

6. 黑帽变换(Bottom-hat)¶

  • 定义:闭运算结果减去原图。
  • 效果:
    • 提取图像中的暗细节。
    • 用于增强图像中的暗点或小孔。
  • 示例:在X光图像中,黑帽变换可以用于检测骨骼中的微小裂缝。

三、高级形态学操作¶

1. 细化(Thinning)¶

  • 原理:通过迭代腐蚀操作,逐步去除物体边界像素,直到得到单像素宽的骨架。
  • 效果:
    • 提取物体的骨架。
    • 减少数据量,便于后续处理。
  • 示例:在字符识别中,细化操作可以将字符转换为单像素宽的骨架,便于特征提取。

2. 粗化(Thickening)¶

  • 原理:通过迭代膨胀操作,逐步加粗物体。
  • 效果:
    • 增加物体的厚度。
    • 用于连接断裂的物体。
  • 示例:在指纹识别中,粗化操作可以增强指纹纹路的连续性。

3. 骨架提取(Skeletonization)¶

  • 原理:类似于细化操作,但更注重保持物体的拓扑结构。
  • 效果:
    • 提取物体的中心线。
    • 保留物体的形状信息。
  • 示例:在血管图像中,骨架提取可以用于分析血管的拓扑结构。

4. 区域填充(Region Filling)¶

  • 原理:从种子点开始,通过迭代膨胀操作填充区域。
  • 效果:
    • 填充图像中的闭合区域。
    • 用于分割或标记物体。
  • 示例:在二值图像中,区域填充可以用于填充物体内部的空洞。

四、结构元素的选择¶

  • 形状:常见的结构元素形状包括方形、圆形、线性等。
  • 大小:结构元素的大小影响操作的强度。较大的结构元素会导致更强的腐蚀或膨胀效果。
  • 方向:对于线性结构元素,方向会影响操作的各向异性。

图像分割¶


一、基于阈值的分割方法¶

原理:根据像素灰度值设定阈值,将图像分为前景和背景。
适用场景:目标与背景灰度差异明显的图像。

  1. 全局阈值法

    • 方法:如Otsu算法,通过最大化类间方差自动确定阈值。
    • 优点:计算简单,适合简单场景。
    • 缺点:对光照不均或复杂背景敏感。
  2. 自适应阈值法

    • 方法:如局部二值化(Local Thresholding),根据局部区域动态调整阈值。
    • 优点:适应光照变化,适合复杂背景。

二、基于边缘的分割方法¶

原理:检测图像中灰度或颜色突变的边缘,连接边缘形成区域。
适用场景:目标边缘清晰、对比度高的图像。

  1. 边缘检测算子

    • Sobel、Prewitt、Canny:通过梯度计算检测边缘。
    • Canny算子:结合高斯滤波、非极大值抑制和双阈值处理,效果更鲁棒。
  2. 边缘连接

    • 方法:通过霍夫变换或最小生成树算法连接断续边缘。
    • 挑战:噪声干扰可能导致边缘断裂或误检。

三、基于区域的分割方法¶

原理:根据像素相似性将图像划分为区域。
适用场景:目标内部颜色或纹理均匀的图像。

  1. 区域生长

    • 步骤:选择种子点,逐步合并相似像素。
    • 优点:简单直观,适合小区域分割。
    • 缺点:对种子点选择敏感,可能过度生长。
  2. 区域分裂与合并

    • 步骤:从整图开始,分裂不均匀区域,合并相似区域。
    • 优点:适应复杂场景,但计算复杂度高。
  3. 分水岭算法

    • 原理:将图像视为地形图,通过“淹水”过程划分区域。
    • 优点:适合分割粘连物体,但易受噪声影响。

四、基于聚类的分割方法¶

原理:将像素聚类为具有相似特征的组。
适用场景:无监督学习场景。

  1. K-means聚类

    • 步骤:初始化K个中心点,迭代分配像素并更新中心。
    • 优点:简单高效,但K值需预设。
  2. Mean Shift聚类

    • 原理:通过密度梯度上升找到聚类中心。
    • 优点:无需预设K值,适合非均匀分布。

五、基于图论的分割方法¶

原理:将图像建模为图,通过优化分割准则划分节点。
适用场景:需要全局优化的复杂场景。

  1. Graph Cut

    • 原理:将图像分割转化为最小割问题,通过最大化流算法求解。
    • 优点:结果稳定,但计算复杂度高。
  2. Normalized Cut(Ncut)

    • 改进:引入归一化项,避免偏好小区域分割。
  3. GrabCut

    • 原理:结合用户交互(如矩形框)和Graph Cut,实现半自动分割。
    • 优点:交互简单,适合复杂背景。

六、基于深度学习的分割方法¶

原理:利用卷积神经网络(CNN)自动学习特征,实现端到端分割。
适用场景:复杂场景、大规模数据集。

  1. 全卷积网络(FCN)

    • 创新:用全卷积层替代全连接层,输出像素级分类。
    • 优点:首次实现端到端语义分割。
  2. U-Net

    • 结构:编码器-解码器结构,结合跳跃连接保留细节。
    • 优点:适合小数据集,医学图像分割经典方法。
  3. Mask R-CNN

    • 原理:在目标检测基础上增加分割分支,实现实例分割。
    • 优点:同时检测和分割多个实例。
  4. DeepLab系列

    • 创新:引入空洞卷积(Atrous Convolution)和条件随机场(CRF)后处理。
    • 优点:扩大感受野,提升边界精度。
  5. Transformer-based方法

    • 方法:如Swin Transformer,利用自注意力机制捕捉全局依赖。
    • 优点:适合长距离依赖场景,但计算资源需求高。

七、其他方法¶

  1. 基于活动轮廓模型(Snake)

    • 原理:通过能量最小化使曲线变形至目标边界。
    • 优点:适合形状先验已知的场景。
  2. 超像素分割

    • 方法:如SLIC算法,将图像划分为局部相似的超像素。
    • 优点:减少计算量,常作为预处理步骤。
  3. 弱监督/无监督分割

    • 方法:利用少量标注数据或无标注数据训练模型。
    • 挑战:标注成本高,但应用前景广阔。

八、方法选择建议¶

  1. 简单场景:优先选择阈值法、边缘检测。
  2. 复杂背景:考虑深度学习方法(如U-Net、Mask R-CNN)。
  3. 交互式需求:GrabCut或基于超像素的方法。
  4. 实时性要求:轻量级网络(如MobileNetV3 + DeepLabV3+)。

九、总结¶

图像分割方法的选择需综合考虑数据特性、计算资源和任务需求。传统方法(如阈值、边缘检测)计算简单,但泛化能力有限;深度学习方法(如FCN、U-Net)性能强大,但依赖大量标注数据。未来趋势包括:

  • 弱监督/无监督学习:减少标注依赖。
  • 多模态融合:结合RGB、深度、热成像等多源数据。
  • 轻量化模型:优化计算效率,适应边缘设备。

基本函数¶

cv2¶

imread()¶

cv2.imread() 用于读取图片文件,imread() 函数有两个参数,第一个参数是图片路径,第二个参数表示读取图片的形式,有三种

cv2.IMREAD_COLOR:加载彩色图片,这个是默认参数,可以直接写 1
cv2.IMREAD_GRAYSCALE:以灰度模式加载图片,可以直接写 0
cv2.IMREAD_UNCHANGED:包括 alpha,可以直接写 -1

imwrite()¶

cv2.imwrite() 用于保存一个图像。第一个参数是要保存的文件名,第二个参数是要保存的图像。

resize( )¶

第一个参数是图片
第二个参数是要缩放的大小,如(256, 256)图像放缩到256

cv2.waitKey()¶

是一个用于等待用户按键输入的函数。默认参数 0 表示无限期等待,直到用户按下任意键为止

cv2.waitKey(1): 等待 1 毫秒,如果在这段时间内没有按键按下,则继续执行后续代码。这通常用于视频处理或实时显示图像时,以控制帧率

cv2.destroyAllWindows()¶

关闭所有OpenCV窗口

cvtColor()¶

gray_image = cv2.cvtColor(image_path, cv2.COLOR_BGR2GRAY)
第一个参数是源图像
第二个参数是转换代码:
cv2.COLOR_BGR2GRAY:BGR 到灰度
cv2.COLOR_GRAY2BGR:灰度到 BGR
cv2.COLOR_BGR2HSV:BGR 到 HSV
cv2.COLOR_HSV2BGR:HSV 到 BGR
HSV 表示色调(Hue)、饱和度(Saturation)和明度(Value)

imshow()¶

两个参数:一个是窗口的名称(字符串类型),另一个是要显示的图像

threshold()¶

用于应用固定阈值操作来将灰度图像转换为二值图像
它接收几个参数,包括输入图像、用于分类的阈值、最大值(当像素值超过(或低于,取决于阈值类型)阈值时赋予的值)以及阈值类型
ret, thresh_image = cv2.threshold(src, x,y, Methods)
第一个参数 src 指原图像,原图像应该是灰度图
第二个参数 x 指用来对像素值进行分类的阈值
第三个参数 y 指当像素值高于(有时是小于)阈值时应该被赋予的新的像素值
第四个参数 Methods 指不同的不同的阈值方法
ret 是阈值,thresh_image 是二值化后的图像

常用的阈值类型主要包括:

  • cv2.THRESH_OTSU 或 cv2.THRESH_TRIANGLE

自动计算最佳阈值

  • cv2.THRESH_BINARY二进制阈值化:

将图像转换为仅包含两个可能像素值的图像(二值图像) 如果像素值高于阈值,则将其设置为最大值(如255) 如果像素值低于或等于阈值,则将其设置为0

  • cv2.THRESH_BINARY_INV反二进制阈值化:

与二进制阈值化相反 如果像素值高于阈值,则将其设置为0 如果像素值低于或等于阈值,则将其设置为最大值(如255)

  • cv2.THRESH_TRUNC截断阈值化:

将图像中大于阈值的像素值设置为阈值本身 小于或等于阈值的像素值保持不变

  • cv2.THRESH_TOZERO阈值化为0:

将图像中小于或等于阈值的像素值设置为0 大于阈值的像素值保持不变

  • cv2.THRESH_TOZERO_INV反阈值化为0:

与阈值化为0相反 将图像中大于阈值的像素值设置为0 小于或等于阈值的像素值保持不变

GaussianBlur() 高斯平滑¶

cv2.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])

  • src: 输入图像矩阵,可为单通道或多通道,多通道时分别对每个通道进行卷积
  • ksize:高斯卷积核的大小,宽,高都为奇数,且可以不相同
  • sigmaX: 一维水平方向高斯卷积核的标准差
  • sigmaY: 一维垂直方向高斯卷积核的标准差,默认值为0,表示与sigmaX相同
  • dst:输出图像矩阵,大小和数据类型都与src相同,例如(3,5)
  • borderType:填充边界类型

boxFilter() 均值平滑¶

cv2.boxFilter(src, ddepth, ksize[, dst[, normalize[, borderType]]])

  • src: 输入图像对象矩阵,
  • ddepth:数据格式,位深度-1代表使用原图深度
  • ksize:高斯卷积核的大小,格式为(宽,高)
  • dst:输出图像矩阵,大小和数据类型都与src相同
  • anchor:卷积核锚点,默认(-1,-1)表示卷积核的中心位置
  • normalize:是否归一化
  • borderType:填充边界类型

blur() 均值平滑¶

cv2.blur(src, ksize[, dst[, anchor[, borderType]]])

  • src: 输入图像对象矩阵,可以为单通道或多通道
  • ksize:高斯卷积核的大小,格式为(宽,高)
  • dst:输出图像矩阵,大小和数据类型都与src相同
  • anchor:卷积核锚点,默认(-1,-1)表示卷积核的中心位置
  • borderType:填充边界类型

medianBlur() 中值平滑¶

cv2.medianBlur(src, ksize[, dst])

  • src: 输入图像对象矩阵,可以为单通道或多通道
  • ksize:核的大小,格式为 3
  • dst:输出图像矩阵,大小和数据类型都与src相同

bilateralFilter() 双边滤波¶

cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]])

  • src: 输入图像对象矩阵,可以为单通道或多通道
  • d: 用来计算卷积核的领域直径,如果d<=0,从sigmaSpace计算d
  • sigmaColor: 颜色空间过滤器的sigma值,这个参数的值越大,表明该像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域
  • sigmaSpace: 坐标空间中滤波器的sigma值,如果该值较大,则意味着颜色相近的较远的像素将相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色

当d>0时,d指定了邻域大小且与sigmaSpace无关,否则d正比于sigmaSpace

Sobel()¶

用于计算图像梯度的函数,常用于边缘检测。通过 Sobel 算子分别计算图像在水平(x)和垂直(y)方向上的梯度,从而突出图像的边缘特征。 Sobel 算子通过卷积核计算梯度:

  • 水平方向核(检测垂直边缘):
    [-1  0  1]
    [-2  0  2]
    [-1  0  1]
    
  • 垂直方向核(检测水平边缘):
    [-1 -2 -1]
    [ 0  0  0]
    [ 1  2  1]
    

cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])
  1. src:输入图像(单通道或多通道的灰度/彩色图像)。
  2. ddepth:输出图像的深度(数据类型),常用值:
    • cv2.CV_64F(64 位浮点,保留负梯度)
    • cv2.CV_8U(8 位无符号,默认,但会丢失负梯度)
  3. dx:x 方向导数的阶数(如 1 表示计算水平梯度)。
  4. dy:y 方向导数的阶数(如 1 表示计算垂直梯度)。
  5. ksize(可选):Sobel 核的大小,必须是奇数(如 1, 3, 5, 7),默认 3。
    • ksize=1 时使用 3x1 或 1x3 核(无高斯平滑)。
    • ksize=-1 时使用 Scharr 算子(更敏感的边缘检测)。
  6. scale(可选):梯度值的缩放因子(默认 1)。
  7. delta(可选):添加到结果中的偏移量(默认 0)。
  8. borderType(可选):边界填充方式(如 cv2.BORDER_DEFAULT)。

In [ ]:
# 使用示例:
## 1. 计算水平和垂直梯度

import cv2
import numpy as np

# 读取图像并转为灰度图
image = cv2.imread("image.jpg", cv2.IMREAD_GRAYSCALE)

# 计算 x 和 y 方向的梯度
sobel_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
sobel_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)

# 转换为绝对值并映射到 8 位无符号
sobel_x_abs = cv2.convertScaleAbs(sobel_x)
sobel_y_abs = cv2.convertScaleAbs(sobel_y)

# 合并梯度
sobel_combined = cv2.addWeighted(sobel_x_abs, 0.5, sobel_y_abs, 0.5, 0)

# 显示结果
cv2.imshow("Original", image)
cv2.imshow("Sobel X", sobel_x_abs)
cv2.imshow("Sobel Y", sobel_y_abs)
cv2.imshow("Combined Sobel", sobel_combined)
cv2.waitKey(0)
cv2.destroyAllWindows()


## 2. 使用 Scharr 算子(更敏感的边缘检测)
scharr_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=-1)
scharr_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=-1)


### 关键注意事项:
# 1. **负梯度处理**:
#    - 使用 `cv2.CV_64F` 保留负梯度,再通过 `cv2.convertScaleAbs()` 转换为 8 位。
#    - 直接使用 `cv2.CV_8U` 会丢失负梯度信息(边缘方向可能不准确)。

# 2. **梯度方向**:
#    - `dx=1, dy=0`:检测垂直边缘(对水平变化敏感)。
#    - `dx=0, dy=1`:检测水平边缘(对垂直变化敏感)。

# 3. **噪声影响**:
#    - Sobel 对噪声敏感,通常先使用高斯模糊(`cv2.GaussianBlur()`)平滑图像。

putText() 在图像上添加文本¶

cv2.putText(

  • img,
  • text, 要添加的文本内容(字符串类型)
  • org, 文本左下角在图像中的坐标(元组 (x, y))。示例:(50, 50) 表示文本从图像左上角向右 50 像素、向下 50 像素的位置开始
  • fontFace, 字体类型
  • fontScale, 字体缩放比例(浮点数)。1.0 表示原始大小,2.0 放大一倍
  • color, 文本颜色(BGR 格式元组)。示例:(255, 0, 0) 表示蓝色,(0, 255, 0) 表示绿色
  • thickness=1, 文本线条粗细(整数,默认 1)
  • lineType=cv2.LINE_8, 线条类型(抗锯齿选项)cv2.LINE_AA:抗锯齿(平滑边缘,推荐)cv2.LINE_8:默认(无抗锯齿,速度快)
  • bottomLeftOrigin=False 坐标原点方向(布尔值,默认 False)。若为 True,则 org 表示文本左上角坐标;若为 False,表示左下角坐标

)

calcHist() 直方图¶

hist = cv2.calcHist([img], [0], None, [256], [0, 256])

注意,除了mask,其他四个参数都要带[]号.后面两个参数基本不用管

  • images: 输入图像,应该是灰度图或者多通道图像。可以是一个图像列表
  • channels: 指定要计算直方图的通道索引。例如,对于彩色图像,[0] 表示蓝色通道,[1] 表示绿色通道,[2] 表示红色通道。如果是灰度图,可以传入 [0]
  • mask: 掩膜图像。如果为 None,则计算整个图像的直方图。如果提供了掩膜,则只计算掩膜中非零像素对应的区域
  • histSize: 每个通道的直方图分箱(bin)数量。例如,[256] 表示将灰度值分成 256 个区间(0-255)
  • ranges: 每个通道的像素值范围。例如,[0, 256] 表示像素值从 0 到 255(OpenCV 的范围是左闭右开,即 [0, 256])
  • hist (可选): 输出直方图数组。如果提供,函数会将结果写入该数组
  • accumulate (可选): 是否累加直方图。如果为 True,则新的直方图会累加到已有的直方图上

equalizeHist() 直方图均衡化¶

equ=equalizeHist(img)

对图像操作而不是对直方图,结果得到的是均衡化后的图片

matplotlib.pyplot¶

import matplotlib.pyplot as plt

figure() 图形窗口¶

创建一个新的图形窗口,特别是需要在同一脚本中创建多个独立的图形时

  • num: 图形窗口的编号或名称。如果指定数字,则创建或激活该编号的图形窗口;如果指定字符串,则创建或激活该名称的图形窗口
  • figsize: 指定图形窗口的大小,格式为 (width, height),单位为英寸
  • dpi: 指定图形窗口的分辨率,单位为每英寸点数(dots per inch)
  • facecolor: 指定图形窗口的背景颜色
  • edgecolor: 指定图形窗口的边框颜色

plot()¶

  • x: X 轴数据
  • y: Y 轴数据
  • label: 图例标签
  • color: 线条颜色 'r' (红色), 'b' (蓝色), 'g' (绿色), 'k' (黑色), 'c' (青色), 'm' (洋红), 'y' (黄色), 'w' (白色)
  • linewidth 或 lw: 线条宽度
  • linestyle 或 ls: 线条样式 '-' (实线), '--' (虚线), '-.' (点划线), ':' (点线)
  • marker: 数据点的标记样式 '.' (点), ',' (像素点), 'o' (圆圈), 'v' (向下三角形), '^' (向上三角形), '<' (左三角形), '>' (右三角形), '1' (下三叉), '2' (上三叉), '3' (左三叉), '4' (右三叉), 's' (正方形), 'p' (五角星), '*' (星号), 'h' (六边形1), 'H' (六边形2), '+' (加号), 'x' (叉号), '|' (垂直线), '_' (水平线)
  • markersize 或 ms: 标记大小
  • markerfacecolor 或 mfc: 标记填充颜色
  • markeredgecolor 或 mec: 标记边缘颜色

subplots()¶

plt.subplot(m, n, p)逗号可以省略 plt.subplots(1, 5, figsize=(20, 4)) 创建一个包含5个子图的图形窗口,大小为20*4

使用 subplots 创建子图,axes 是一个包含所有子图对象的数组 每个子图对象,即 Axes 对象代表图形窗口中的一个绘图区域 通过索引 axes[i],访问和操作特定的子图

axes[0].imshow(imageA1) axes[0].set_title("Image A1") axes[0].axis('off')去掉坐标轴

显示整个图形窗口¶

plt.show()

title,xlabel,ylabel¶

plt.title('Multiple Line Plots with Different Styles') plt.xlabel('X-axis Label') plt.ylabel('Y-axis Label')

legend()¶

添加图例

grid(True)¶

添加网格

show()¶

显示所有当前打开的图形窗口 当调用 plt.show() 时,程序会暂停执行,直到所有的图形窗口都被关闭

imshow()¶

用于在 Axes 对象上显示图像数据

参数: X: 要显示的图像数据,通常是二维数组 cmap: 颜色映射表(colormap),用于灰度图像 vmin, vmax: 显示数据范围内的最小值和最大值 aspect: 图像的宽高比控制 interpolation: 插值方法,用于平滑图像

plt.imshow(img, "gray")

numpy¶

基本定义¶

二值化¶

图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果

计算处理¶

除法运算divide()¶

In [ ]:
# 在 python 语言中,图像的除法运算可以调用 opencv-python 库中的 divide() 函数进行;

# 导入库
import numpy as np
import cv2
# 定义 X,Y 矩阵
X = np.array([[255,0,75,0],[44,255,100,3]])
Y = np.array([[0,0,25,4],[0,1,50,3]])
# 调用 divide() 函数进行除法运算
result = cv2.divide(X, Y)
# 打印结果
print(result)

# 输出:

# [[  0   0   3   0]
#  [  0 255   2   1]]
# 结果说明:在保存成图像时,会自动截取(如果大于 255,则取 255)。

乘法运算multiply()¶

In [ ]:
# 在 python 语言中,图像的乘法运算可以调用 opencv-python 库中的 multiply() 函数进行。

result = cv2.multiply(X, Y)

减法运算subtract()¶

In [ ]:
# 在 python 语言中,图像的减法运算可以调用 opencv-python 库中的 subtract() 函数进行;

import numpy as np
import cv2

X = np.array([[255,0,75,0],[44,255,100,3]])
Y = np.array([[50,50,50,50],[50,50,50,50]])

result = cv2.subtract(X, Y)

print(result)

# 输出:

# [[205 -50  25 -50]
#  [ -6 205  50 -47]]
# 结果说明:在保存成图像时,会自动截取(如果小于 0,则取 0)

加法运算add()¶

In [ ]:
import numpy as np
import cv2
X = np.array([[255,0,75,0],[44,255,100,3]])
Y = np.array([[50,50,50,50],[50,50,50,50]])

result = cv2.add(X, Y)

print(result)

# 输出:

# [[305  50 125  50]
#  [ 94 305 150  53]]
# 结果说明:在保存成图像时,会自动截取(如果大于255,则取255)

异或运算^¶

In [ ]:
# 相同为0
# 在 python 语言中,异或运算可以使用 ^ 表示

import numpy as np
import cv2

X = cv2.imread('/data/workspace/myshixun/step4/A/image1.jpg', 0)
Y = cv2.imread('/data/workspace/myshixun/step4/A/image2.jpg', 0)

result = X ^ Y

cv2.imwrite("/data/workspace/myshixun/step4/C/result.jpg",result)

print(np.sum(result))

或运算|¶

In [ ]:
# 在 python 语言中,或运算用 | 表示

result = X | Y

二值化与阈值化处理¶

全局阈值法方法就是将图像中低于某个阈值的像素设置为黑色(0),而其他的设置为白色(255)

In [ ]:
import cv2
import numpy as np
from matplotlib import pyplot as plt


def hdss_su():
    img = cv2.imread('home/OpenCV_2zhih/imgs/timg2.jpg')
    # 任务1先将img转灰度
    Image = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    # 再对其使用两个阈值方法对其二值化,阈值为127
    ret, BINARY = cv2.threshold(Image,127,255,cv2.THRESH_BINARY)
    ret, BINARY_INV = cv2.threshold(Image,127,255,cv2.THRESH_BINARY_INV)
    # 传出值Image, BINARY, BINARY_INV

    
    titles = ['Image','BINARY','BINARY_INV']
    images = [Image, BINARY, BINARY_INV]
    for i in (range(3)):
        plt.subplot(1, 3, i + 1)
        plt.imshow(images[i], 'gray')
        plt.title(titles[i])
        plt.xticks([]), plt.yticks([])
    # plt.savefig("home/OpenCV_2zhih/2z_out/test.png")
    return images

Opencv中阈值化操作和自适应阈值化:
cv2.threshold(src, thresh, maxval, type[, dst]) -> retval, dst

  • src 参数表示输入图像(多通道,8位或32位浮点)
  • thresh 参数表示阈值
  • maxval 参数表示与THRESH_BINARY和THRESH_BINARY_INV阈值类型一起使用设置的最大值一般为255
  • type 参数表示阈值类型
  • retval 参数表示返回的阈值。若是全局固定阈值算法,则返回 thresh 参数值。若是全局自适应阈值算法,则返回自适应计算得出的合适阈值
  • dst 参数表示输出与src相同大小和类型以及相同通道数的图像
  • type 参数单独选择上述五种阈值类型时,是固定阈值算法,效果比较差

例子:ret, binary = cv2.threshold(gray, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)
OTSU为大律法,全局自适应阈值,第二个参数值0可改为任意数字或不写,因为它会被忽略
注:cv2.THRESH_OTSU也可单独使用,不一定要写成和固定阈值算法结合的形式。单独写和结合起来写,都是自适应阈值算法优先

例子:ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_TRIANGLE)
TRIANGLE法,全局自适应阈值,第二个参数值0可改为任意数字但不起作用,适用于单个波峰
注:cv2.THRESH_TRIANGLE也可单独使用,不一定要写成和固定阈值算法结合的形式。单独写和结合起来写,都是自适应阈值算法优先

In [ ]:
import cv2


def threshold_us():
    image = cv2.imread('home/OpenCV_yz/img/lp.jpg')
    # 将图片从BGR颜色空间转换为灰度图
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 任务1 TRIANGLE自适应阈值
    # 使用cv2.threshold函数,其中cv2.THRESH_TRIANGLE表示自动计算一个合适的阈值(基于直方图)
    ret, TRIANGLE_img = cv2.threshold(gray,0,255,cv2.THRESH_TRIANGLE)


    # 任务2 OTSU自适应阈值
    # cv2.THRESH_OTSU也用于自动计算阈值,但算法与THRESH_TRIANGLE不同
    # 注意:在使用THRESH_OTSU时,通常不需要手动指定阈值参数(第一个参数),因为它会被忽略
    ret, OTSU_img = cv2.threshold(gray,0,255,cv2.THRESH_OTSU)

    # 任务3 TRUNC截断阈值(200)
    # 对于大于200的像素值,它们会被截断为200;小于200的像素值保持不变
    # 注意:THRESH_TRUNC模式下,maxval参数(这里是255)实际上不会被用到,但仍需设置
    ret, TRUNC_img = cv2.threshold(gray,200,255,cv2.THRESH_TRUNC)

    # 任务4 TOZERO归零阈值(100)
    # 对于小于100的像素值,它们会被设置为0;大于或等于100的像素值保持不变
    ret, TOZERO_img = cv2.threshold(gray,100,255,cv2.THRESH_TOZERO)


    # 将处理后的图像保存到指定的文件夹中
    cv2.imwrite('home/OpenCV_yz/img_out/TRIANGLE_img.jpg',TRIANGLE_img)
    cv2.imwrite('home/OpenCV_yz/img_out/OTSU_img.jpg',OTSU_img)
    cv2.imwrite('home/OpenCV_yz/img_out/TRUNC_img.jpg',TRUNC_img)
    cv2.imwrite('home/OpenCV_yz/img_out/TOZERO__img.jpg',TOZERO_img)
    # 返回处理后的图像
    return  TRIANGLE_img, OTSU_img, TRUNC_img, TOZERO_img

平滑处理¶

高斯平滑¶

高斯平滑即采用高斯卷积核对图像矩阵进行卷积操作 高斯卷积核是一个近似服从高斯分布的矩阵,随着距离中心点的距离增加,其值变小。这样进行平滑处理时,图像矩阵中锚点处像素值权重大,边缘处像素值权重小

dst = cv2.GaussianBlur(src,ksize,sigmaX,sigmay,borderType) 参数说明: src: 输入图像矩阵,可为单通道或多通道,多通道时分别对每个通道进行卷积 dst:输出图像矩阵,大小和数据类型都与src相同 ksize:高斯卷积核的大小,宽,高都为正奇数,且可以不相同,格式为(宽,高) 核大小:核越大,参与卷积的像素越多,平滑效果越明显,但计算量增加 奇偶性:必须为奇数以确保存在明确的中心点,避免核偏移。若输入偶数,OpenCV 会报错 方向性:若宽度 ≠ 高度(如 (5,3)),水平和垂直方向的平滑强度不同,可能导致图像在特定方向更模糊 sigmaX: 一维水平方向高斯卷积核的标准差 标准差越大:高斯分布越平缓,更多周围像素参与计算,平滑效果更强 默认值:若未指定(sigmaX=0),OpenCV 会根据 ksize 自动计算(公式:sigma = 0.3*((ksize-1)/2 - 1) + 0.8) sigmaY: 一维垂直方向高斯卷积核的标准差 默认值为0,表示与sigmaX相同 borderType:填充边界类型 cv2.BORDER_REPLICATE:复制边缘像素值 cv2.BORDER_CONSTANT:填充固定值(如 0,默认黑色) cv2.BORDER_REFLECT:镜像反射边缘像素

见'高斯滤波.py'

均值平滑¶

高斯卷积核,对卷积框中像素值赋予不同权重,而均值平滑赋予相同权重 opencv的boxFilter()函数和blur()函数都能用来进行均值平滑。

cv2.boxFilter(src,ddepth,ksize,dst,anchor,normalize,borderType) dst=cv2.boxFilter(src,ddepth,ksize,anchor,normalize,borderType) 参数说明: src: 输入图像对象矩阵, ddepth:输出图像的位深度(数据格式) -1:与输入图像深度相同。 ksize:高斯卷积核的大小,必须为正奇数,格式为(宽,高) 同上 dst:输出图像矩阵,大小和数据类型都与src相同 anchor:卷积核锚点,默认(-1,-1)表示卷积核的中心位置 normalize:是否归一化 True(默认):计算均值(均值平滑),输出为均值滤波结果 False:计算邻域像素和(积分图像),输出为邻域像素和,可用于快速计算 Haar 特征 borderType:填充边界类型 同上

cv2.blur(src,ksize,dst,anchor,borderType) dst=cv2.blur(src,ksize,anchor,borderType) 参数说明: src: 输入图像对象矩阵,可以为单通道或多通道 ksize:高斯卷积核的大小,格式为(宽,高) dst:输出图像矩阵,大小和数据类型都与src相同 anchor:卷积核锚点,默认(-1,-1)表示卷积核的中心位置 borderType:填充边界类型

与高斯平滑相比:边缘模糊更严重,简单降噪,计算效率高 见'均值滤波.py'

中值平滑¶

是对核中所有像素值排序得到中间值,用该中间值来代替锚点值。 opencv中利用medianBlur()来进行中值平滑。

cv2.medianBlur(src,ksize,dst) dst=cv2.medianBlur(src,ksize) 参数说明: src: 输入图像对象矩阵,可以为单通道或多通道 ksize:核的大小,格式为 3
必须为正奇数 dst:输出图像矩阵,大小和数据类型都与src相同

优点:对椒盐噪声(随机黑白点)效果显著,且能保留边缘。 缺点:对高斯噪声(连续渐变噪声)效果有限,且计算复杂度较高(需排序) 见'排序统计滤波.py'

双边滤波¶

双边滤波是一种非线性滤波方法,相比于上面几种平滑算法,双边滤波在平滑的同时还能保持图像中物体的轮廓信息 它通过结合空间距离权重(空间域)和像素值相似性权重(值域)实现这一目标 双边滤波在高斯平滑的基础上引入了灰度值相似性权重因子,所以在构建其卷积核核时,要同时考虑空间距离权重和灰度值相似性权重 在进行卷积时,每个位置的邻域内,根据和锚点的距离d构建距离权重模板,根据和锚点灰度值差异r构建灰度值权重模板,结合两个模板生成该位置的卷积核。

opencv中的bilateralFilter()函数实现了双边滤波,其参数对应如下:

dst = cv2.bilateralFilter(src,d,sigmaColor,sigmaSpace,borderType) 参数说明: src: 输入图像对象矩阵,可以为单通道或多通道 d: 用来计算卷积核的领域直径,如果d<=0,从sigmaSpace自动计算d 邻域大小:d 越大,参与滤波的像素越多,但计算量显著增加 推荐值:通常取 5~9,过大可能导致过度平滑 与 sigmaSpace 的关系:若 d > 0,邻域直径为 d,否则邻域直径与 sigmaSpace 成正比 sigmaColor:值域(颜色空间)的标准差 值越大:颜色差异较大的像素也会被混合,可能导致颜色区域过度平滑,边缘保留能力下降 值越小:仅颜色相近的像素参与滤波,边缘保留更好,但去噪能力减弱 推荐值:通常取 30~100,需根据图像噪声水平调整 sigmaSpace: 空间域(坐标空间)的标准差 值越大:颜色相近的较远的像素对滤波结果影响增强,从而使更大的区域中足够相似的颜色获取相同的颜色,平滑范围扩大,但可能导致边缘模糊 值越小:仅邻近像素参与滤波,边缘保留更好,但去噪能力减弱 推荐值:通常取 30~100,需与 sigmaColor 协同调整。

示例¶

见'平滑处理.py'

直方图¶

  1. 概念

直方图是一种统计报告图,形式上是一个个的长条形,长条形的面积表示频数,高度表示频数组距,宽度表示组距。当宽度相同时,一般就用长条形长度表示频数 直方图反映了图像像素分布的统计特性 2. 基本性质 以图形化参数来显示图片曝光精确度的手段,其描述的是图片显示范围内影像的灰度分布曲线 它可以帮助分析图片的曝光水平等一些信息。直方图的左边显示了图像的阴影信息``中间显示了图像的中间色调信息``右边显示了图像的高亮信息 3. 重要性质: 反映了图像中的灰度分布规律。它描述每个灰度级具有的像素个数,但不包含这些像素在图像中的位置信息 直方图和图像之间的关系是多对一的关系。任何一幅特定的图像都有唯一的直方图与之对应,但不同的图像可以有相同的直方图。 如果一幅图像有两个不相连的区域组成,并且每个区域的直方图已知,则整幅图像的直方图是该两个区域的直方图之和 4. 应用 根据直方图的形态可以大致推断图像质量的好坏。由于图像包含有大量的像元,其像元灰度值的分布应符合概率统计分布规律。假定像元的灰度值是随机分布的,那么其直方图应该是正态分布 图像的灰度值是离散变量,因此直方图表示的是离散的概率分布。若以各灰度级的像元数占总像元数的比例值为纵坐标轴做出图像的直方图,将直方图中各条形的最高点连成一条外轮廓线,纵坐标的比例值即为某灰度级出现的概率密度,轮廓线可近似看成图像相应的连续函数的概率分布曲线

直方图与线性图¶

plt 绘制直方图和线性图

plt.hist(data,bins=30, normed=0, facecolor="red", alpha=0.7) 参数 作用 data 必选参数,绘图数据 bins 直方图的长条形数目,可选项,默认为10 normed 是否将得到的直方图向量归一化,可选项,默认为0,代表不归一化,显示频数。normed=1,表示归一化,显示频率。 facecolor 长条形的颜色 edgecolor 长条形边框的颜色 alpha 透明度

In [ ]:
import matplotlib
import numpy as np
import matplotlib.pyplot as plt


def student(data, x, y):
    '''
    根据输入数据将直方图与线形图绘制在同一面板中,并设置直方图为红色,线形图为蓝色
    :return: None
    '''

    # 创建一个新的图形,设置figsize为(10, 10)
    plt.figure(figsize=(10, 10))

    # 绘制直方图
    plt.hist(data, facecolor="red",alpha=0.7)
 
    # 绘制线形图
    plt.plot(x, y, color="blue")

    # 保存图形
    plt.savefig('Task4/img/T1.png')

绘制直方图¶

cv2 绘制直方图 cv2.calcHist([img], [0], None, [256], [0,256]) 见'绘制直方图.py'

二维直方图¶

plt.hist2d()

灰度直方图的计算¶

见'灰度直方图的计算.py'

直方图均衡化¶

直方图均衡化是灰度变换的一个重要应用,它高效且易于实现,广泛应用于图像增强处理中
图像的像素灰度变化是随机的,直方图的图形高低不齐,直方图均衡化就是用一定的算法使直方图大致平和
均衡化处理后的图象只能是近似均匀分布。本质是扩大量化间隔,而减少量化级别,
因此,原来灰度不同的像素经处理后可能变的相同,形成了一片的相同灰度的区域,各区域之间有明显的边界,从而出现了伪轮廓
灰度直方图均衡化的算法,简单地说,就是把直方图的每个灰度级进行归一化处理,求每种灰度的累积分布,得到一个映射的灰度映射表,然后根据相应的灰度值来修正原图中的每个像素

equalizeHist()

见 '直方图均衡化.py'

图像分割¶

  1. 基于RGB,HSV

  2. OTSU

  3. 基于边缘的分割方法(Canny 边缘检测,Sobel 算子)

    • 图像中前景和背景的边缘清晰。形状规则、边缘明显的物体
  4. 基于区域的分割方法(区域生长,分水岭算法)

    • 图像中前景和背景的纹理或颜色相似性明显。适用于复杂场景,但可能对噪声敏感
  5. 基于聚类的分割方法(K-Means 聚类)

    • 适用于彩色图像分割,尤其是前景和背景颜色差异明显的场景。无需手动调整阈值,但需要指定聚类数量 K
  6. 基于深度学习的分割方法

    • 适用于复杂场景,尤其是前景和背景颜色或纹理相似时。需要大量标注数据和计算资源
  7. 基于图论的分割方法(GrabCut)

    • 需要用户交互分割
In [ ]:
import cv2
from matplotlib import pyplot as plt
import numpy as np

M=cv2.imread('/data/bigfiles/M.jpg')#BGR
M_rgb=cv2.cvtColor(M,cv2.COLOR_BGR2RGB)
R=M_rgb[:,:,0]
G=M_rgb[:,:,1]
B=M_rgb[:,:,2]
M_hsv=cv2.cvtColor(M_rgb,cv2.COLOR_RGB2HSV)
# 分割黄色花朵部分
# 定义黄色的HSV范围(可以根据实际情况调整)
lower_yellow = np.array([20, 100, 100])
upper_yellow = np.array([30, 255, 255])
# 创建掩膜
mask = cv2.inRange(M_hsv, lower_yellow, upper_yellow)
# 应用掩膜获取黄色部分
E = cv2.bitwise_and(M_rgb, M_rgb, mask=mask)
# 计算E的像素值总和
sum_pixels = np.sum(E)

# 显示图像
plt.figure(figsize=(15, 10))
 
# 显示原图
plt.subplot(2, 3, 1)
plt.imshow(M_rgb)
plt.title('M')
plt.axis('off')
 
# 显示R分量图
plt.subplot(2, 3, 2)
plt.imshow(R, cmap='Reds')
plt.title('R')
plt.axis('off')
 
# 显示G分量图
plt.subplot(2, 3, 3)
plt.imshow(G, cmap='Greens')
plt.title('G')
plt.axis('off')
 
# 显示B分量图
plt.subplot(2, 3, 4)
plt.imshow(B, cmap='Blues')
plt.title('B')
plt.axis('off')
 
# 显示HSV图
plt.subplot(2, 3, 5)
# 将HSV转换为RGB以便显示(因为Matplotlib不直接支持HSV显示)
M_hsv_rgb = cv2.cvtColor(M_hsv, cv2.COLOR_HSV2RGB)
plt.imshow(M_hsv_rgb)
plt.title('HSV')
plt.axis('off')
 
# 显示分割后的E图
plt.subplot(2, 3, 6)
plt.imshow(E)
plt.title('E')
plt.axis('off')
 
plt.tight_layout()
plt.show()
 
# 打印E的像素值总和
print(f"SUM:{sum_pixels}")

Canny¶

In [ ]:
import cv2
import numpy as np
from matplotlib import pyplot as plt

M = cv2.imread('M.jpg', cv2.IMREAD_GRAYSCALE)  # 读取为灰度图
edges = cv2.Canny(M, 100, 200)  # Canny边缘检测

plt.imshow(edges, cmap='gray')
plt.title('Canny Edge Detection')
plt.axis('off')
plt.show()

分水岭算法¶

In [ ]:
import cv2
import numpy as np
from matplotlib import pyplot as plt

M = cv2.imread('M.jpg')
gray = cv2.cvtColor(M, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 去除噪声
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)

# 确定背景区域
sure_bg = cv2.dilate(opening, kernel, iterations=3)

# 确定前景区域
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)

# 找到未知区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)

# 标记标签
ret, markers = cv2.connectedComponents(sure_fg)
markers = markers + 1
markers[unknown == 255] = 0

# 应用分水岭算法
markers = cv2.watershed(M, markers)
M[markers == -1] = [255, 0, 0]  # 标记边界为红色

plt.imshow(cv2.cvtColor(M, cv2.COLOR_BGR2RGB))
plt.title('Watershed Segmentation')
plt.axis('off')
plt.show()

K-Means 聚类¶

In [ ]:
import cv2
import numpy as np
from matplotlib import pyplot as plt

M = cv2.imread('M.jpg')
Z = M.reshape((-1, 3))  # 转换为二维数组,形状为 (像素数, 3)
Z = np.float32(Z)  # 转换为float32类型

# 定义K-Means参数
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 3  # 聚类数量
ret, label, center = cv2.kmeans(Z, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)

# 将聚类结果转换回图像
center = np.uint8(center)
res = center[label.flatten()]
res2 = res.reshape((M.shape))

plt.imshow(cv2.cvtColor(res2, cv2.COLOR_BGR2RGB))
plt.title('K-Means Segmentation')
plt.axis('off')
plt.show()

Grabcut¶

In [ ]:
import cv2
import numpy as np
from matplotlib import pyplot as plt

M = cv2.imread('M.jpg')
mask = np.zeros(M.shape[:2], np.uint8)

# 定义矩形区域(包含前景)
bgd_model = np.zeros((1, 65), np.float64)
fgd_model = np.zeros((1, 65), np.float64)
rect = (50, 50, 450, 290)  # 矩形坐标 (x, y, w, h)

# 应用GrabCut算法
cv2.grabCut(M, mask, rect, bgd_model, fgd_model, 5, cv2.GC_INIT_WITH_RECT)

# 创建掩膜
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
result = M * mask2[:, :, np.newaxis]

plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
plt.title('GrabCut Segmentation')
plt.axis('off')
plt.show()

边缘检测¶

频率域滤波¶

In [ ]:
# 低通滤波
def ideal_low_pass_filter(image, cutoff):
    # 计算图像的二维傅里叶变换
    f = np.fft.fft2(image)
    
    # 将傅里叶变换的低频分量移到频谱的中心
    fshift = np.fft.fftshift(f)
    
    # 获取图像的行数和列数
    rows, cols = image.shape
    
    # 计算频谱的中心位置
    crow, ccol = rows // 2, cols // 2
    
    # 创建一个与图像大小相同的零矩阵作为掩码
    mask = np.zeros((rows, cols), np.uint8)
    
    # 在掩码的中心区域设置截止频率的范围,并将该区域的值设为1
    mask[crow - cutoff:crow + cutoff, ccol - cutoff:ccol + cutoff] = 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)
    
    return img_back
In [ ]:
# 高通滤波
def ideal_high_pass_filter(image, cutoff):

    f = np.fft.fft2(image)
    
    fshift = np.fft.fftshift(f)
    
    rows, cols = image.shape
    
    crow, ccol = rows // 2, cols // 2
    
    # 创建一个与图像大小相同的全1矩阵作为掩码
    mask = np.ones((rows, cols), np.uint8)
    
    # 在掩码的中心区域设置截止频率的范围,并将该区域的值设为0
    mask[crow - cutoff:crow + cutoff, ccol - cutoff:ccol + cutoff] = 0
    
    fshift_filtered = fshift * mask
    

    f_ishift = np.fft.ifftshift(fshift_filtered)
    
    img_back = np.fft.ifft2(f_ishift)
    
    img_back = np.abs(img_back)
    
    return img_back