Bootstrap

图像处理基础———python图像处理基础操作介绍

图像处理基础———python图像处理基础操作介绍

在数字化时代,图像处理已成为我们日常生活和工作中不可或缺的一部分。从社交媒体上的美颜滤镜,到医学影像分析,再到自动驾驶汽车的视觉感知系统,图像处理技术都发挥着至关重要的作用。Python,作为一种功能强大且易于学习的编程语言,为图像处理提供了丰富的库和工具,使得开发者能够轻松地处理和操作图像数据。

本篇博客将带领大家走进Python图像处理的世界,介绍一些基础操作,帮助读者快速上手。我们将通过实际代码示例,展示如何使用Python进行图像的读取、保存、显示,以及基本的图像变换和处理。无论你是图像处理领域的新手,还是希望进一步提升技能的开发者,相信本文都能为你提供一些有益的指导和启发。

基本概念

图像,作为视觉信息的载体,广泛存在于我们的日常生活中。从广义上分类,图像可以分为模拟图像数字图像两种。模拟图像,顾名思义,模拟图像是以连续变化的物理量来表示的图像,如同早期的胶片摄影,其细节和色彩在胶片上以连续的化学变化形式存在。然而,随着技术的飞速发展,数字图像逐渐成为了主流。

数字图像则是通过将模拟图像进行采样和量化得到的,它由一系列的像素点组成,每个像素点都有其特定的位置和颜色信息。这种数字化的表达方式使得图像能够方便地被计算机存储、处理和传输。也正因为数字图像的这种离散性和可计算性,它成为了计算机视觉领域的主要研究对象。

计算机视觉,作为一个跨学科的领域,主要研究如何让计算机从图像或视频中获取信息、理解内容并作出决策。在这个过程中,数字图像处理技术发挥着至关重要的作用。无论是图像的预处理、特征提取,还是目标检测与识别,都离不开数字图像处理技术的支持。通过运用各种算法和技术,计算机视觉系统能够对数字图像进行深入的分析和理解,从而实现对视觉信息的有效利用。

采样过程

在模拟图像转换为数字图像的过程中,采样是一个关键环节。采样是指将模拟图像在空间上进行离散化处理:
采样的基本概念:采样是将时间上或空间上连续的信号(在图像处理中通常指模拟图像)转换成离散信号(数字图像)的过程。在图像处理中,采样特指将连续的二维图像信号转换为离散的像素点集合。

采样的数学表示:假设模拟图像是一个连续函数 f ( x , y ) f(x, y) f(x,y),其中 x x x y y y表示图像上的空间坐标, f ( x , y ) f(x, y) f(x,y)表示在坐标 ( x , y ) (x, y) (x,y)处的像素值(如灰度值或颜色信息)。采样过程可以表示为在特定的空间坐标 ( x i , y j ) (x_i, y_j) (xi,yj)上取值,其中 i i i j j j是整数索引,代表离散化的空间位置。

采样的具体步骤

  • 确定采样网格:首先,需要确定一个采样网格,即确定采样点 ( x i , y j ) (x_i, y_j) (xi,yj)的位置。这些位置通常按照规则的网格排列,如矩形网格。
  • 执行采样:在每个采样点 ( x i , y j ) (x_i, y_j) (xi,yj)上,对模拟图像函数 f ( x , y ) f(x, y) f(x,y)进行取值,得到该点的像素值 f ( x i , y j ) f(x_i, y_j) f(xi,yj)。这个过程就是将连续的图像信号在特定的空间位置上“取样”。
  • 形成数字图像:经过采样后,我们得到了一组离散的像素值,这些像素值按照采样网格的排列形成了一个二维数组(或矩阵),即数字图像。

采样定理与采样频率:在采样过程中,一个重要的概念是采样频率,它决定了采样点的密集程度。根据香农采样定理(Shannon’s Sampling Theorem),为了能够从采样信号中完全恢复出原始信号,采样频率必须大于或等于原始信号中最高频率成分的两倍。在图像处理中,这意味着采样点的间距必须足够小,以确保能够捕捉到图像中的所有重要细节。数学上,如果原始图像的频谱中的最高频率为 f max f_{\text{max}} fmax,则采样频率 f s f_s fs应满足:

f s ≥ 2 f max f_s \geq 2f_{\text{max}} fs2fmax

在二维图像处理中,这个条件需要同时在水平和垂直方向上得到满足。

采样对图像质量的影响:采样点的数量和分布直接影响到数字图像的质量和分辨率。采样点越多(即采样频率越高),所得到的数字图像越能接近原始的模拟图像,细节表现能力越强。但同时,增加采样点也意味着需要更多的存储空间和处理资源。因此,在实际应用中需要在图像质量和资源消耗之间找到平衡。

图像的直方图

图像的直方图是一种在图像处理中广泛应用的工具,它能够有效地反映图像中像素强度的分布情况。图像直方图是一种统计图表,用于表示数字图像中不同像素强度值的频率分布。在灰度图像中,直方图通常表示0-255范围内各个灰度级的像素数量或频率。直方图只反映图像中像素强度值的统计情况,并不包含像素的位置信息。因此,具有相同直方图的两幅图像可能在视觉上完全不同。

计算步骤:首先,构造一个长度为256的向量(对应256个灰度级);然后,初始化该向量为0;接着,遍历图像中的每个像素,根据像素的灰度值在向量中对应的位置进行计数;最后,得到的向量即为图像的直方图。直方图通常以图形的形式展示,横轴表示灰度级,纵轴表示对应灰度级的像素数量或频率。这样可以直观地看出图像中各个灰度级的分布情况。

图像直方图在图像处理、计算机视觉和模式识别等领域有广泛应用。例如,在图像分割中,可以利用直方图来确定阈值,从而将目标从背景中分离出来;在图像检索中,可以利用颜色直方图来快速有效地从大规模图像数据库中检索出所需的图像。图像直方图具有计算代价较小、对图像平移、旋转和缩放等变换具有不变性等优点。这使得直方图成为一种高效且稳定的图像特征表示方法。

接下来,我们对下方的图像进行直方图提取与处理:

import cv2  
import numpy as np  
import matplotlib.pyplot as plt  
%matplotlib inline

# 展示图像
image = cv2.imread('img\cells.png')  
plt.imshow(image)

在这里插入图片描述

# 读取图像  
image = cv2.imread('img\cells.png', 0)  # 0 表示以灰度模式读取图像  
  
# 提取直方图信息  
hist, bins = np.histogram(image.ravel(), 256, [0, 256])  

# 可视化直方图  
plt.hist(image.ravel(), 256, [0, 256], color='r')  
plt.xlim([0, 256])  
plt.show() 

在这里插入图片描述

这样我们就可以看到图像的灰度直方图信息了,从图像中,我们观察到灰度值集中在200以上,因此我们就可以将灰度值小于200的像素点设置为0,看看图片。

# 计算阈值  
threshold = 200
  
# 设置阈值
image[image <= threshold] = 0  

# 展示图像  
plt.imshow(image, cmap='gray')  
plt.show()

在这里插入图片描述

可以看到,这样我们可以成功提取出图像中细胞的位置信息了。

空间域图像增强

灰度变换

图像的空间域像素变换是数字图像处理中的一种基本技术,它直接对图像的像素值进行操作以改变图像的视觉效果或提取有用信息:

  1. 图像反转(Image Negation)

    • 数学公式 s = L − 1 − r s = L - 1 - r s=L1r
      其中, s s s 是输出灰度级, r r r 是输入灰度级, L L L 是灰度级的最大值(例如,对于8位灰度图像, L = 256 L = 256 L=256)。

    • 描述:图像反转是将图像的灰度级进行颠倒,使黑变白,白变黑。这种变换通常用于增强暗色图像中的白色或灰色细节。

image = cv2.imread('img\cells.png') 
# 进行图像反转
image_inv = cv2.bitwise_not(image)

# 展示图像
plt.imshow(image_inv)

在这里插入图片描述

  1. 对数变换(Logarithmic Transformation)

    • 数学公式 s = c log ⁡ ( 1 + r ) s = c \log(1 + r) s=clog(1+r)
      其中, c c c 是一个常数,用于调整曲线的位置和形状。

    • 描述:对数变换可以将图像中范围较窄的低灰度值映射到较宽的灰度范围,同时压缩高灰度值。这种变换有助于扩展暗部细节,同时压缩亮部细节。

image = cv2.imread('img\cells.png') 
# 进行对数变换
# 确保图像数据类型为float32,以便进行对数运算  
image_float = image.astype(float)  
  
# 对数变换公式 s = c * log(1 + r)  
c = 255 / np.log(256)  # 常数c,用于调整曲线的位置和形状  
log_transformed = c * np.log(1 + image_float)  
  
# 数据类型转换回uint8,并进行归一化  
log_transformed = np.array(log_transformed, dtype=np.uint8)  
log_transformed = cv2.normalize(log_transformed, None, 0, 255, cv2.NORM_MINMAX)  
  
# 展示图像
plt.imshow(log_transformed)

在这里插入图片描述

  1. 幂次变换(Power-Law Transformation)

    • 数学公式 s = c r γ s = cr^\gamma s=crγ
      其中, c c c γ \gamma γ 是正常数, γ \gamma γ 称为伽马值。

    • 描述:幂次变换,也称为伽马校正,可以根据伽马值的不同来拉伸或压缩图像的灰度级。当 γ > 1 \gamma > 1 γ>1 时,该变换会拉伸低灰度级并压缩高灰度级;当 γ < 1 \gamma < 1 γ<1 时,效果相反。这种变换常用于调整图像的对比度。

image = cv2.imread('img\cells.png') 
# 进行幂次变换
# 确保图像数据类型为float32,以便进行幂次运算  
image_float = image.astype(float)  
  
# 幂次变换公式 s = cr^\gamma
c = 1  # 常数c,用于调整曲线的位置和形状
power_transformed = c * (image_float ** (0.4))
  
# 数据类型转换回uint8,并进行归一化
power_transformed = np.array(power_transformed, dtype=np.uint8)
power_transformed = cv2.normalize(power_transformed, None, 0, 255, cv2.NORM_MINMAX)
  
# 展示图像
plt.imshow(power_transformed)

在这里插入图片描述

  1. 分段线性变换(Piecewise Linear Transformation)

    • 数学公式:(无统一公式,因情况而异)

    • 描述:分段线性变换涉及将灰度级分成几个区间,并对每个区间应用不同的线性变换。这种方法可以用于对比度拉伸、灰度级切割等目的,以增强图像的特定部分。

这些空间域像素变换类型在数字图像处理中非常有用,可以帮助改善图像的视觉效果,提取特征,或者为后续的图像分析和处理步骤做准备。在实际应用中,可以根据具体需求和图像特性选择合适的变换方法。

直方图均衡

图像进行空间域的直方图均衡是一种常用的图像增强技术,旨在通过调整图像的灰度分布来提高图像的对比度和清晰度。直方图均衡的基本原理是通过一个灰度映像函数,将原灰度直方图改造成均匀分布的直方图,从而增加像素灰度值的动态范围,达到增强图像整体对比度的效果。设原始图像的灰度级为 r r r,其取值范围为 [ 0 , L − 1 ] [0, L-1] [0,L1],其中 L L L是灰度级的数量(对于8位灰度图像, L = 256 L=256 L=256)。直方图均衡化的过程可以表示为寻找一个映射函数 T ( r ) T(r) T(r),使得输出图像的灰度级 s s s具有均匀的直方图分布。

常用的直方图均衡类型

  1. 全局直方图均衡化(Histogram Equalization, HE)

    全局直方图均衡化是最基本的直方图均衡方法。它对整个图像的灰度分布进行调整,使得均衡化后的图像具有更广泛的灰度级范围和更高的对比度。数学上,全局直方图均衡化的变换函数可以表示为:

    s = T ( r ) = ∑ i = 0 r n i N s = T(r) = \sum_{i=0}^{r} \frac{n_i}{N} s=T(r)=i=0rNni

    其中, n i n_i ni是灰度级为 i i i的像素数量, N N N是图像中的总像素数。这个函数将原始图像的灰度级映射到新的灰度级上,以实现直方图的均衡化。

image = cv2.imread('img\cells.png') 
# 分离颜色通道  
r, g, b = cv2.split(image)  
  
# 对每个通道进行全局直方图均衡化  
r_eq = cv2.equalizeHist(r)  
g_eq = cv2.equalizeHist(g)  
b_eq = cv2.equalizeHist(b)  
  
# 合并处理后的通道  
equalized_image = cv2.merge([r_eq, g_eq, b_eq])  
  
# 显示原始图像和均衡化后的图像  
plt.figure(figsize=(10, 5))  
  
plt.subplot(1, 2, 1)  
plt.title('Original Image')  
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))  # OpenCV使用BGR格式,转换为RGB以正确显示  
plt.axis('off')  
  
plt.subplot(1, 2, 2)  
plt.title('Equalized Image')  
plt.imshow(cv2.cvtColor(equalized_image, cv2.COLOR_BGR2RGB))  # 转换为RGB格式以正确显示  
plt.axis('off')  
  
plt.show()

在这里插入图片描述

  1. 自适应直方图均衡化(Adaptive Histogram Equalization, AHE)

    自适应直方图均衡化是一种改进的直方图均衡方法,它将图像划分成多个小区域,并对每个区域分别进行直方图均衡化。这种方法可以更好地适应图像中不同区域的局部对比度需求。然而,AHE可能会导致图像失真和噪声放大。

  2. 对比度受限制自适应直方图均衡化(Contrast Limited Adaptive Histogram Equalization, CLAHE)

    CLAHE是AHE的一种改进方法,它通过对每个小区域的直方图进行裁剪来限制局部对比度的增强程度,从而避免了AHE中可能出现的噪声放大和图像失真问题。CLAHE算法复杂度相对较高,但处理后的图像质量通常更好。

滤波

图像进行空间域的滤波是数字图像处理中的一项重要技术,其目的通常是为了增强图像质量、去除噪声或提取特定特征。读者可以发现滤波进行的操作与卷积神经网络中的卷积操作非常相似。

  1. 低通滤波

低通滤波主要用于平滑图像,去除高频噪声,同时保留图像的低频部分。其数学原理在于通过滤波器函数与图像进行卷积运算,以减小图像中灰度值的突变,达到平滑效果。常用的低通滤波器包括均值滤波器和高斯滤波器。

均值滤波:对于图像中的每个像素,取其邻域内像素值的平均作为新的像素值。公式表示为:
g ( x , y ) = 1 M ∑ ( s , t ) ∈ S x y f ( x , y ) g(x,y) = \frac{1}{M} \sum_{(s,t) \in S_{xy}} f(x,y) g(x,y)=M1(s,t)Sxyf(x,y)
其中, g ( x , y ) g(x,y) g(x,y) 是输出图像, f ( x , y ) f(x,y) f(x,y) 是输入图像在 ( x , y ) (x,y) (x,y)位置像素值, S x y S_{xy} Sxy 是以 ( x , y ) (x,y) (x,y) 为中心的邻域, M M M 是邻域内的像素数量。

高斯滤波:采用正态分布计算出的权重与图像进行卷积。高斯滤波器的公式为:
G ( x , y ) = 1 2 π σ 2 e − x 2 + y 2 2 σ 2 G(x,y) = \frac{1}{2\pi\sigma^2} e^{-\frac{x^2+y^2}{2\sigma^2}} G(x,y)=2πσ21e2σ2x2+y2
其中, σ \sigma σ 是高斯函数的标准差,决定了高斯滤波器的宽度。

image = cv2.imread('img\cells.png') 
# 应用均值滤波,其中ksize是滤波器的大小,例如(5, 5)  
blurred_image = cv2.blur(image, (5, 5))  

# 应用高斯滤波,其中ksize是滤波器的大小,例如(5, 5),sigmaX是X方向上的标准差  
blurred_image_Gaussian = cv2.GaussianBlur(image, (5, 5), sigmaX=0)  

# 显示原始图像和滤波后的图像  
plt.figure(figsize=(10, 5))  
  
plt.subplot(1, 3, 1)  
plt.title('Original Image')  
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))  # OpenCV使用BGR格式,转换为RGB以正确显示  
plt.axis('off')  
  
plt.subplot(1, 3, 2)  
plt.title('blurred_image')  
plt.imshow(cv2.cvtColor(blurred_image, cv2.COLOR_BGR2RGB))  # 转换为RGB格式以正确显示  
plt.axis('off')  

plt.subplot(1, 3, 3)  
plt.title('blurred_image_Gaussian')  
plt.imshow(cv2.cvtColor(blurred_image_Gaussian, cv2.COLOR_BGR2RGB))  # 转换为RGB格式以正确显示  
plt.axis('off')  
  
plt.show()

在这里插入图片描述

  1. 中值滤波

中值滤波是一种非线性滤波方法,对于去除椒盐噪声特别有效。其原理是将像素邻域内的所有像素值排序后取中值作为新的像素值。数学表达式为:
g ( x , y ) = med { f ( x , y ) } , ( x , y ) ∈ S x y g(x,y) = \text{med}\{f(x,y)\}, (x,y) \in S_{xy} g(x,y)=med{f(x,y)},(x,y)Sxy
其中, med \text{med} med 表示取中值的操作, S x y S_{xy} Sxy 是以 ( x , y ) (x,y) (x,y) 为中心的邻域。

image = cv2.imread('img\cells.png') 
# 应用中值滤波,其中ksize是滤波器的大小,例如(5, 5)
median_image = cv2.medianBlur(image, 5)

# 显示滤波后的图像
plt.imshow(median_image)

在这里插入图片描述

  1. 高通滤波

高通滤波用于增强图像的边缘和细节信息。它通过抑制低频部分而突出高频部分来实现。高通滤波可以通过从原始图像中减去低通滤波后的图像得到,数学上表达为:
g ( x , y ) = f ( x , y ) − LPF [ f ( x , y ) ] g(x,y) = f(x,y) - \text{LPF}[f(x,y)] g(x,y)=f(x,y)LPF[f(x,y)]
其中, LPF \text{LPF} LPF 表示低通滤波操作。

image = cv2.imread('img\cells.png') 
# 应用高通滤波
high_pass_image = cv2.Laplacian(image, cv2.CV_64F)
# Laplacian算子是一种二阶导数算子,具有旋转不变性,可以满足不同方向的图像边缘锐化(边缘检测)的要求。
# 在本质上,Laplacian边缘检测是使用图像矩阵与Laplacian核进行卷积运算。这实际上是计算图像中任意一点与其在水平方向和垂直方向上4个相邻点平均值的差值。

# 显示滤波后的图像
plt.imshow(high_pass_image)

在这里插入图片描述

图像的空间域滤波是数字图像处理中的关键技术,不同类型的滤波器根据其数学原理和应用目的对图像进行不同的处理。低通滤波主要用于平滑图像和去噪,中值滤波对于去除特定类型的噪声非常有效,而高通滤波则用于增强图像的边缘信息。这些滤波方法都基于一定的数学公式和算法,通过卷积运算或其他数学操作来实现对图像的特定处理效果。

频域图像增强

在图像处理中,频域滤波是一种重要的技术,它允许我们根据不同的频率特性对图像进行增强、去噪或其他形式的处理。这种处理通常涉及将图像从空间域(即我们通常看到的图像)转换到频域,在频域中进行操作,然后再将结果转换回空间域。下面将结合数学公式介绍频域滤波的基本概念,并举例说明低通、高通和同态滤波等常用类型。

频域滤波的基本原理是利用傅里叶变换将图像从空间域转换到频域。在频域中,图像被表示为一系列不同频率的正弦波和余弦波的叠加。滤波操作就是在频域中对这些频率成分进行选择性地增强或抑制。

二维傅里叶变换(2D Fourier Transform)是在二维空间中对信号或图像进行频谱分析的一种数学工具。与一维傅里叶变换类似,二维傅里叶变换也是将一个信号(在二维情况下通常是一个图像)分解为一系列不同频率的正弦波和余弦波的组合。

对于一个二维函数 f ( x , y ) f(x, y) f(x,y),其二维傅里叶变换可以定义为:

F ( u , v ) = ∫ − ∞ ∞ ∫ − ∞ ∞ f ( x , y ) e − j 2 π ( u x + v y ) d x d y F(u, v) = \int_{-\infty}^{\infty} \int_{-\infty}^{\infty} f(x, y) e^{-j2\pi(ux + vy)} dx dy F(u,v)=f(x,y)ej2π(ux+vy)dxdy

其中, F ( u , v ) F(u, v) F(u,v) 是二维频域中的表示, u u u v v v 是频率变量,分别对应于 x x x y y y 方向上的空间频率, j j j 是虚数单位。

二维傅里叶变换在图像处理中有广泛应用,如滤波、图像增强、特征提取等。通过二维傅里叶变换,我们可以将图像从空间域转换到频域,对频率成分进行分析和操作,然后再通过逆二维傅里叶变换将处理后的频域信号转换回空间域,从而实现对原始图像的处理和修改。

逆二维傅里叶变换的公式为:

f ( x , y ) = ∫ − ∞ ∞ ∫ − ∞ ∞ F ( u , v ) e j 2 π ( u x + v y ) d u d v f(x, y) = \int_{-\infty}^{\infty} \int_{-\infty}^{\infty} F(u, v) e^{j2\pi(ux + vy)} du dv f(x,y)=F(u,v)ej2π(ux+vy)dudv

在实际应用中,由于图像是离散的,我们通常使用离散二维傅里叶变换(2D Discrete Fourier Transform, 2D DFT)及其快速算法(如快速傅里叶变换,FFT)来进行处理。

image = cv2.imread('img\cells.png') 
  
# OpenCV默认读取图像的颜色顺序是BGR,转换为RGB以便正确显示  
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  
  
# 对每个通道进行二维傅里叶变换  
fourier_transform_b = np.fft.fft2(image[:,:,0])  
fourier_transform_g = np.fft.fft2(image[:,:,1])  
fourier_transform_r = np.fft.fft2(image[:,:,2])  
  
# 将零频分量移动到频谱中心  
fourier_transform_b_shifted = np.fft.fftshift(fourier_transform_b)  
fourier_transform_g_shifted = np.fft.fftshift(fourier_transform_g)  
fourier_transform_r_shifted = np.fft.fftshift(fourier_transform_r)  
  
# 计算每个通道的频谱幅度  
magnitude_b = 20 * np.log(np.abs(fourier_transform_b_shifted) + 1e-10)  
magnitude_g = 20 * np.log(np.abs(fourier_transform_g_shifted) + 1e-10)  
magnitude_r = 20 * np.log(np.abs(fourier_transform_r_shifted) + 1e-10)  
  
# 堆叠幅度图以可视化  
magnitude = np.dstack((magnitude_r, magnitude_g, magnitude_b))  
# 将幅度图转换为灰度图像以便正确显示
magnitude = np.array(magnitude, dtype=np.uint8)
magnitude = cv2.normalize(magnitude, None, 0, 255, cv2.NORM_MINMAX)
  
# 展示原始图像和频谱图  
plt.figure(figsize=(12, 6))  
  
plt.subplot(1, 2, 1)  
plt.imshow(image)  
plt.title('Original Color Image')  
plt.axis('off')  
  
plt.subplot(1, 2, 2)  
plt.imshow(magnitude)  
plt.title('Color Magnitude Spectrum')  
plt.axis('off')  
  
plt.show()  

在这里插入图片描述

# 进行逆变换  
inverse_transform_b = np.fft.ifft2(fourier_transform_b)  
inverse_transform_g = np.fft.ifft2(fourier_transform_g)  
inverse_transform_r = np.fft.ifft2(fourier_transform_r)  
  
# 组合逆变换后的通道  
reconstructed_image = np.dstack((np.abs(inverse_transform_r), np.abs(inverse_transform_g), np.abs(inverse_transform_b)))  
  
# 由于逆变换可能得到复数,我们取绝对值来重构图像  
reconstructed_image = np.uint8(np.clip(reconstructed_image, 0, 255))  
  
# 将图像转为BGR格式以便正确显示
reconstructed_image = cv2.cvtColor(reconstructed_image, cv2.COLOR_RGB2BGR)
# 展示逆变换后的图像  
plt.imshow(reconstructed_image)  
plt.title('Reconstructed Color Image')  
plt.axis('off')  
plt.show()

在这里插入图片描述

1. 低通滤波器

原理:低通滤波器(Low-pass filter)允许低频信号通过,而阻止或减弱高频信号。在图像处理中,这通常用于去除噪声或平滑图像。

数学表示:设 H ( u , v ) H(u, v) H(u,v) 为滤波器的传递函数,则低通滤波器可以表示为:

H ( u , v ) = { 1 , if  D ( u , v ) ≤ D 0 0 , if  D ( u , v ) > D 0 H(u, v) = \begin{cases} 1, & \text{if } D(u, v) \leq D_0 \\ 0, & \text{if } D(u, v) > D_0 \end{cases} H(u,v)={1,0,if D(u,v)D0if D(u,v)>D0

其中, D ( u , v ) D(u, v) D(u,v) 是频率域中某点到原点的距离, D 0 D_0 D0 是滤波器的截止频率。

image = cv2.imread('img\cells.png', cv2.IMREAD_GRAYSCALE)  
  
# 进行傅里叶变换  
dft = cv2.dft(np.float32(image), flags=cv2.DFT_COMPLEX_OUTPUT)  
dft_shift = np.fft.fftshift(dft)  
  
# 创建低通滤波器掩模  
rows, cols = image.shape  
crow, ccol = rows // 2, cols // 2  # 中心位置  
mask = np.zeros((rows, cols, 2), np.uint8)  
r = 80  # 设置低通滤波器的半径  
center = [crow, ccol]  
x, y = np.ogrid[:rows, :cols]  
mask_area = (x - center[0]) ** 2 + (y - center[1]) ** 2 <= r*r  
mask[mask_area] = 1  
  
# 应用掩模并进行逆DFT  
fshift = dft_shift * mask  
f_ishift = np.fft.ifftshift(fshift)  
img_back = cv2.idft(f_ishift)  
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])  
  
# 归一化到0-255之间  
img_back = np.uint8(cv2.normalize(img_back, None, 0, 255, cv2.NORM_MINMAX))  
  
# 显示图像  
plt.subplot(121), plt.imshow(image, cmap='gray')  
plt.title('Input Image'), plt.xticks([]), plt.yticks([])  
plt.subplot(122), plt.imshow(img_back, cmap='gray')  
plt.title('Low Pass Filter'), plt.xticks([]), plt.yticks([])  
plt.show()

在这里插入图片描述

2. 高通滤波器

原理:高通滤波器(High-pass filter)与低通滤波器相反,它允许高频信号通过,而阻止或减弱低频信号。这通常用于增强图像的边缘和细节。

数学表示:高通滤波器的传递函数可以表示为:

H ( u , v ) = { 0 , if  D ( u , v ) ≤ D 0 1 , if  D ( u , v ) > D 0 H(u, v) = \begin{cases} 0, & \text{if } D(u, v) \leq D_0 \\ 1, & \text{if } D(u, v) > D_0 \end{cases} H(u,v)={0,1,if D(u,v)D0if D(u,v)>D0

与低通滤波器相反,高通滤波器在频率低于 D 0 D_0 D0 时阻止信号通过。

3. 同态滤波

原理:同态滤波是一种技术,通过非线性映射将原始信号转换到另一个可以使用线性滤波器的域进行处理。在图像处理中,该技术特别适用于处理由光照不均匀导致的图像质量下降问题。

数学表示:同态滤波的过程可以简要描述为以下几个步骤:

  1. 对原始图像 f ( x , y ) f(x, y) f(x,y) 进行对数变换,得到 s ( x , y ) = ln ⁡ [ f ( x , y ) ] s(x, y) = \ln[f(x, y)] s(x,y)=ln[f(x,y)]
  2. s ( x , y ) s(x, y) s(x,y) 进行傅里叶变换,得到 S ( u , v ) S(u, v) S(u,v)
  3. 在频域中应用一个线性滤波器 H ( u , v ) H(u, v) H(u,v),得到滤波后的频域表示 S ′ ( u , v ) = H ( u , v ) ⋅ S ( u , v ) S'(u, v) = H(u, v) \cdot S(u, v) S(u,v)=H(u,v)S(u,v)
  4. S ′ ( u , v ) S'(u, v) S(u,v) 进行逆傅里叶变换,得到 s ′ ( x , y ) s'(x, y) s(x,y)
  5. 最后,通过指数变换得到增强后的图像 f ′ ( x , y ) = exp ⁡ [ s ′ ( x , y ) ] f'(x, y) = \exp[s'(x, y)] f(x,y)=exp[s(x,y)]

同态滤波的关键在于设计合适的线性滤波器 H ( u , v ) H(u, v) H(u,v),以便根据具体需求增强图像。

图像增广

深度神经网络成功应用的前提是拥有庞大的数据集。图像增广技术能够通过一系列随机变化,生成既相似又有所区别的训练样本,有效增加训练集的大小。同时,采用图像增广还能通过随机改变训练样本来削弱模型对特定属性的依赖,进而提升其泛化能力。例如,我们可以通过多种裁剪方式,让目标对象出现在图像的不同位置,以此减少模型对对象位置的依赖性。此外,调整图像的亮度和颜色等因素,也可以降低模型对颜色的敏感度。

裁剪是从原始图像中选择一个区域并去除其余部分的过程。这可以帮助模型学习不受图像特定区域限制的特征。

# 读取图像  
image = cv2.imread('img\cells.png')  
  
# 裁剪图像,这里的参数表示裁剪的起始点和结束点
cropped_image = image[500:, :1400]  
plt.imshow(cropped_image)

在这里插入图片描述

翻转是沿垂直或水平轴镜像图像的过程。这有助于模型学习不受图像方向限制的特征。

# 水平翻转  
flipped_image_horizontal = cv2.flip(image, 1)  
  
# 垂直翻转  
flipped_image_vertical = cv2.flip(image, 0)  

# 水平垂直翻转
flipped_image_both = cv2.flip(image, -1)

plt.figure(figsize=(20, 5))  

plt.subplot(1, 4, 1)  
plt.title('Original Image')  
plt.imshow(image)
plt.axis('off')  
  
plt.subplot(1, 4, 2)  
plt.title('flipped_image_horizontal')  
plt.imshow(flipped_image_horizontal)
plt.axis('off')  

plt.subplot(1, 4, 3)  
plt.title('flipped_image_vertical')  
plt.imshow(flipped_image_vertical)
plt.axis('off')  

plt.subplot(1, 4, 4)  
plt.title('flipped_image_both')  
plt.imshow(flipped_image_both)
plt.axis('off')  

plt.show()

在这里插入图片描述

改变图像的色调:可以通过调整图像的HSV(色调、饱和度和亮度)值来改变其颜色。

# 将图像从BGR转换为HSV  
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)  
  
# 调整色调值,例如增加30个单位(范围是0-180)  
hsv_image[:,:,0] = (hsv_image[:,:,0] + 30) % 180  
  
# 将图像从HSV转换回BGR  
modified_image = cv2.cvtColor(hsv_image, cv2.COLOR_HSV2BGR)  
  
# 显示修改后的图像  
plt.imshow(modified_image)

在这里插入图片描述

除了上述的图像处理操作,还有很多图像处理的相关技术可以结合python进行,如可以使用PIL(Python Imaging Library,也称为Pillow)等其他库来处理图像和改变颜色,在接下来深度学习的相关内容中,我们将更多的结合opencv的基础操作,以pytorch中的torchvision库,paddle中的paddle.vision,以及numpy库,进行图像处理的相关操作。

;