一、什么是图像增强?
图像增强是指通过一系列技术和方法对图像进行处理,以改善其视觉效果和特征表现。
1. 主要指标:
(1) 亮度(Brightness):
- 影响图像的整体光照程度。
- 确保图像在视觉上既不过暗也不过亮。
(2) 对比度(Contrast):
- 增强图像中亮部和暗部之间的差异。
- 使得细节更加明显,高对比度有助于更清晰地展示图像的纹理和特征。
(3) 清晰度(Sharpness):
- 提高图像边缘的清晰度。
- 使物体轮廓更加鲜明,便于细节识别。
(4) 色彩饱和度(Color Saturation):
- 增强颜色的丰富性。
- 使图像色彩更加鲜艳,提升视觉吸引力。
(5) 纹理(Texture):
- 突出图像中的纹理细节。
- 增强表面特征,对于医学影像和材料检测等领域尤为重要。
(6) 去噪(Denoising):
- 降低图像中的噪声。
- 提高信号质量,减少噪声对重要细节的干扰。
(7) 增强特征(Feature Enhancement):
- 提高重要特征的可见性。
- 方便观察和分析。
(8) 视觉一致性(Visual Consistency):
- 确保图像不同区域在亮度、对比度和色彩表现上的一致性。
- 便于用户进行全面分析。
2. 应用领域:
图像增强技术广泛应用于多个领域,包括:
- 医学影像:改善X光、CT和MRI图像,以辅助医生诊断。
- 卫星和遥感图像:增强地理数据,支持土地利用分类和环境监测。
- 安防监控:提升监控视频质量,促进人脸识别和行为分析。
- 工业检测:提高质量控制中的产品检测精度。
- 图像搜索和检索:改善图像搜索结果的准确性和相关性。
二、亮度和对比度调整
1. 线性方法
(1) 灰度反转(Gray Inversion)
灰度反转是指将图像中的每个像素值反转,使得图像的亮部变暗,暗部变亮。具体来说,对于一个灰度图像,像素值范围通常是0到255,灰度反转后,像素值G' = 255 - G,其中G是原始像素值,G'是反转后的像素值。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def gray_inversion(image):
"""
灰度反转
:param image: 输入图像(灰度图像)
:return: 处理后的图像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
inverted_image = 255 - image
return inverted_image
def main():
# 读取图像
image = cv2.imread('example.jpg')
if image is None:
print("Error: Could not read image.")
return
# 灰度反转
inverted_image = gray_inversion(image)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(inverted_image, cmap='gray')
plt.title('Inverted Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()import cv2
import numpy as np
import matplotlib.pyplot as plt
def gray_inversion(image):
"""
灰度反转
:param image: 输入图像(灰度图像)
:return: 处理后的图像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
inverted_image = 255 - image
return inverted_image
def main():
# 读取图像
image = cv2.imread('example.jpg')
if image is None:
print("Error: Could not read image.")
return
# 灰度反转
inverted_image = gray_inversion(image)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(inverted_image, cmap='gray')
plt.title('Inverted Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) 对比度拉伸(Contrast Stretching)
对比度拉伸是一种线性变换方法,通过扩展图像的动态范围来增强对比度。具体来说,将图像的最小像素值映射到0,最大像素值映射到255,中间的像素值按比例线性变换。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def contrast_stretching(image):
"""
对比度拉伸
:param image: 输入图像(灰度图像)
:return: 处理后的图像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
min_val = np.min(image)
max_val = np.max(image)
stretched_image = (image - min_val) * (255 / (max_val - min_val))
stretched_image = stretched_image.astype(np.uint8)
return stretched_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 对比度拉伸
stretched_image = contrast_stretching(image)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(stretched_image, cmap='gray')
plt.title('Contrast Stretched Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(3) 对比度和亮度增强(Contrast and Brightness)
对比度和亮度增强是指同时调整图像的对比度和亮度。具体来说,可以通过以下公式进行调整:
其中,G是原始像素值,G'是调整后的像素值,是对比度增益因子(大于1时对比度增强,小于1时对比度减弱),是亮度偏移量(正值使图像变亮,负值使图像变暗)。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def adjust_contrast_brightness(image, alpha=1.0, beta=0):
"""
对比度和亮度增强
:param image: 输入图像
:param alpha: 对比度增益因子(大于1时对比度增强,小于1时对比度减弱)
:param beta: 亮度偏移量(正值使图像变亮,负值使图像变暗)
:return: 处理后的图像
"""
new_image = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)
return new_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 对比度和亮度增强
enhanced_image = adjust_contrast_brightness(image, alpha=1.5, beta=50)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(enhanced_image, cv2.COLOR_BGR2RGB))
plt.title('Contrast and Brightness Enhanced Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
2. 非线性方法
(1) 指数变换(Exponential Transformation)
通过指数函数来调整图像的亮度和对比度。具体公式如下:
其中,G是原始像素值,G'是调整后的像素值,c和k是常数。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def exponential_transformation(image, c=1.0, k=10):
"""
指数变换
:param image: 输入图像(灰度图像)
:param c: 常数c
:param k: 常数k
:return: 处理后的图像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
exp_image = c * (np.exp(image / k) - 1)
exp_image = np.clip(exp_image, 0, 255).astype(np.uint8)
return exp_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 指数变换
exp_image = exponential_transformation(image, c=1.0, k=10)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(exp_image, cmap='gray')
plt.title('Exponential Transformed Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) 伽马变换(Gamma Transformation)
通过伽马函数来调整图像的亮度和对比度。具体公式如下:
其中,G是原始像素值,G'是调整后的像素值,c和是常数。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def gamma_transformation(image, gamma=1.0):
"""
伽马变换
:param image: 输入图像(灰度图像)
:param gamma: 伽马值
:return: 处理后的图像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
inv_gamma = 1.0 / gamma
table = np.array([((i / 255.0) ** inv_gamma) * 255 for i in np.arange(0, 256)]).astype("uint8")
gamma_image = cv2.LUT(image, table)
return gamma_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 伽马变换
gamma_image = gamma_transformation(image, gamma=0.5)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(gamma_image, cmap='gray')
plt.title('Gamma Transformed Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(3) 对数变换(Logarithmic Transformation)
通过对数函数来调整图像的亮度和对比度。具体公式如下:
其中,G是原始像素值,G'是调整后的像素值,c是常数。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def logarithmic_transformation(image, c=1.0):
"""
对数变换
:param image: 输入图像(灰度图像)
:param c: 常数c
:return: 处理后的图像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
log_image = c * np.log1p(image)
log_image = np.clip(log_image, 0, 255).astype(np.uint8)
return log_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 对数变换
log_image = logarithmic_transformation(image, c=255 / np.log1p(np.max(image)))
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(log_image, cmap='gray')
plt.title('Logarithmic Transformed Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
三、直方图均衡化
1. 普通直方图均衡化
直方图均衡化的原理是将图像的灰度直方图展平,使得每个灰度级都有更多的像素分布,从而增强图像的对比度。具体步骤如下:
- 计算灰度直方图:统计图像中每个灰度级的像素数量。
- 计算累积分布函数(CDF):计算每个灰度级的累积概率。
- 映射灰度值:将原始图像中的每个灰度值映射到新的灰度值,使得新的灰度分布更加均匀。
- 生成均衡化后的图像:使用映射后的灰度值生成新的图像。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def histogram_equalization(image):
"""
直方图均衡化
:param image: 输入图像(灰度图像)
:return: 处理后的图像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
equalized_image = cv2.equalizeHist(image)
return equalized_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 直方图均衡化
equalized_image = histogram_equalization(image)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(equalized_image, cmap='gray')
plt.title('Histogram Equalized Image')
plt.axis('off')
plt.tight_layout()
plt.show()
# 显示直方图
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.hist(image.ravel(), 256, [0, 256], color='gray', alpha=0.7)
plt.title('Histogram of Original Image')
plt.xlabel('Pixel Value')
plt.ylabel('Frequency')
plt.subplot(1, 2, 2)
plt.hist(equalized_image.ravel(), 256, [0, 256], color='gray', alpha=0.7)
plt.title('Histogram of Equalized Image')
plt.xlabel('Pixel Value')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
2. 限制对比度自适应直方图均衡化(Contrast Limited Adaptive Histogram Equalization, CLAHE)
限制对比度自适应直方图均衡化在直方图均衡化的基础上进行了改进,通过限制对比度和局部均衡化来避免过度增强图像的对比度,从而减少噪声和不自然的效果。基本原理如下:
- 图像分割:将图像分割成若干个小块(称为“tiles”),每个小块的大小由 tileGridSize 参数指定。
- 局部均衡化:对每个小块分别进行直方图均衡化。为了限制对比度,使用 clipLimit 参数来限制每个小块的直方图中像素值的最大数量。
- 插值平滑:将每个小块均衡化后的结果通过插值技术合并,以避免明显的边界和不连续性。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def clahe_equalization(image, clipLimit=2.0, tileGridSize=(8, 8)):
"""
CLAHE均衡化
:param image: 输入图像(灰度图像)
:param clipLimit: 对比度限制阈值
:param tileGridSize: 小块大小
:return: 处理后的图像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
clahe = cv2.createCLAHE(clipLimit=clipLimit, tileGridSize=tileGridSize)
clahe_image = clahe.apply(image)
return clahe_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# CLAHE均衡化
clahe_image = clahe_equalization(image, clipLimit=2.0, tileGridSize=(8, 8))
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(clahe_image, cmap='gray')
plt.title('CLAHE Equalized Image')
plt.axis('off')
plt.tight_layout()
plt.show()
# 显示直方图
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.hist(image.ravel(), 256, [0, 256], color='gray', alpha=0.7)
plt.title('Histogram of Original Image')
plt.xlabel('Pixel Value')
plt.ylabel('Frequency')
plt.subplot(1, 2, 2)
plt.hist(clahe_image.ravel(), 256, [0, 256], color='gray', alpha=0.7)
plt.title('Histogram of CLAHE Equalized Image')
plt.xlabel('Pixel Value')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
四、空间域(增强)
空间域增强方法直接操作图像的像素值,常用于提高图像的可视性和特征表现。空间域增强方法可以分为线性滤波和非线性滤波两大类。此外,边缘检测也是一种重要的空间域增强技术,用于突出图像中的边缘和细节。
1. 线性滤波
线性滤波通过卷积操作对图像进行处理,常用的线性滤波器包括方框滤波、均值滤波器、高斯滤波器和锐化滤波器等。
(1) 方框滤波(Box Filtering)
方框滤波是一种简单的均值滤波,通过计算每个像素邻域内的平均值来平滑图像。具体来说,对于每个像素,取其邻域内的所有像素值的平均值作为该像素的新值。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def box_filter(image, kernel_size=(3, 3)):
"""
方框滤波
:param image: 输入图像
:param kernel_size: 滤波器大小
:return: 处理后的图像
"""
filtered_image = cv2.boxFilter(image, -1, kernel_size)
return filtered_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 方框滤波
box_filtered_image = box_filter(image, kernel_size=(5, 5))
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(box_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Box Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) 均值滤波器(Mean Filter)
均值滤波器通过计算每个像素邻域内的平均值来平滑图像。具体来说,对于每个像素,取其邻域内的所有像素值的平均值作为该像素的新值。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def mean_filter(image, kernel_size=(3, 3)):
"""
均值滤波
:param image: 输入图像
:param kernel_size: 滤波器大小
:return: 处理后的图像
"""
filtered_image = cv2.blur(image, kernel_size)
return filtered_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 均值滤波
mean_filtered_image = mean_filter(image, kernel_size=(5, 5))
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(mean_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Mean Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(3) 高斯滤波器(Gaussian Filter)
高斯滤波器通过高斯核对图像进行卷积操作,以平滑图像并减少噪声。高斯核的权重分布符合高斯分布,中心权重最大,边缘权重逐渐减小。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def gaussian_filter(image, kernel_size=(5, 5), sigmaX=0):
"""
高斯滤波
:param image: 输入图像
:param kernel_size: 滤波器大小
:param sigmaX: 高斯核的标准差
:return: 处理后的图像
"""
filtered_image = cv2.GaussianBlur(image, kernel_size, sigmaX)
return filtered_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 高斯滤波
gaussian_filtered_image = gaussian_filter(image, kernel_size=(5, 5), sigmaX=0)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(gaussian_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Gaussian Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(4) 锐化滤波器(Sharpening Filter)
锐化滤波器通过增强图像的边缘和细节来提高图像的清晰度。常用的锐化滤波器包括拉普拉斯算子和高通滤波器。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def sharpen_filter(image, kernel_size=(3, 3), alpha=1.5):
"""
锐化滤波
:param image: 输入图像
:param kernel_size: 滤波器大小
:param alpha: 锐化因子
:return: 处理后的图像
"""
# 创建锐化滤波器
kernel = np.array([[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]])
# 应用滤波器
sharpened_image = cv2.filter2D(image, -1, kernel)
# 确保像素值在有效范围内
# sharpened_image = np.clip(sharpened_image, 0, 255).astype(np.uint8)
return sharpened_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 锐化滤波
sharpened_image = sharpen_filter(image, kernel_size=(3, 3), alpha=1.5)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(sharpened_image, cv2.COLOR_BGR2RGB))
plt.title('Sharpened Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
2. 非线性滤波
非线性滤波通过非线性操作对图像进行处理,常用的非线性滤波器包括中值滤波器、双边滤波器、最小/最大滤波器、自适应中值滤波和形态学滤波。
(1) 中值滤波器(Median Filter)
中值滤波器通过计算每个像素邻域内的中值来平滑图像,特别适用于去除椒盐噪声和斑点噪声。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def median_filter(image, kernel_size=3):
"""
中值滤波
:param image: 输入图像
:param kernel_size: 滤波器大小(奇数)
:return: 处理后的图像
"""
filtered_image = cv2.medianBlur(image, kernel_size)
return filtered_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 中值滤波
median_filtered_image = median_filter(image, kernel_size=5)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(median_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Median Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) 双边滤波器(Bilateral Filter)
双边滤波器通过考虑像素值和空间距离来进行滤波,能够在去噪的同时保留图像边缘和细节。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def bilateral_filter(image, d=9, sigmaColor=75, sigmaSpace=75):
"""
双边滤波
:param image: 输入图像
:param d: 每个像素邻域的直径
:param sigmaColor: 颜色空间的标准差
:param sigmaSpace: 坐标空间的标准差
:return: 处理后的图像
"""
filtered_image = cv2.bilateralFilter(image, d, sigmaColor, sigmaSpace)
return filtered_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 双边滤波
bilateral_filtered_image = bilateral_filter(image, d=9, sigmaColor=75, sigmaSpace=75)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(bilateral_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Bilateral Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(3) 最小/最大滤波器(Min/Max Filter)
最小滤波器通过计算每个像素邻域内的最小值来处理图像,最大滤波器通过计算每个像素邻域内的最大值来处理图像。这两种滤波器常用于形态学操作。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def min_filter(image, kernel_size=3):
"""
最小滤波
:param image: 输入图像
:param kernel_size: 滤波器大小(奇数)
:return: 处理后的图像
"""
filtered_image = cv2.erode(image, np.ones((kernel_size, kernel_size), np.uint8))
return filtered_image
def max_filter(image, kernel_size=3):
"""
最大滤波
:param image: 输入图像
:param kernel_size: 滤波器大小(奇数)
:return: 处理后的图像
"""
filtered_image = cv2.dilate(image, np.ones((kernel_size, kernel_size), np.uint8))
return filtered_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 最小滤波
min_filtered_image = min_filter(image, kernel_size=3)
# 最大滤波
max_filtered_image = max_filter(image, kernel_size=3)
# 显示原始图像和处理后的图像
plt.figure(figsize=(12, 6))
plt.subplot(1, 3, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 3, 2)
plt.imshow(cv2.cvtColor(min_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Min Filtered Image')
plt.axis('off')
plt.subplot(1, 3, 3)
plt.imshow(cv2.cvtColor(max_filtered_image, cv2.COLOR_BGR2RGB))
plt.title('Max Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(4) 自适应中值滤波(Adaptive Median Filtering)
自适应中值滤波器通过动态调整滤波器大小来去除噪声,同时保留图像边缘和细节。
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def auto_median_filter(image, max_size):
origen = 3 # 初始窗口大小
board = origen // 2 # 初始应扩充的边界
copy = cv.copyMakeBorder(image, board, board, board, board, borderType=cv.BORDER_REFLECT) # 扩充边界
out_img = np.zeros_like(image, dtype=np.uint8)
def sub_func(src, i, j, size):
# 确保 i 和 j 在有效范围内
if i < 0 or i + size > src.shape[0] or j < 0 or j + size > src.shape[1]:
return src[i, j]
kernel = src[i:i + size, j:j + size]
z_med = np.median(kernel)
z_max = np.max(kernel)
z_min = np.min(kernel)
if z_min < z_med < z_max: # 层次A
if z_min < image[i][j] < z_max: # 层次B
return image[i][j]
else:
return z_med
else:
next_size = size + 2 # 增加尺寸
if next_size <= max_size:
return sub_func(src, i - 1, j - 1, next_size) # 递归调用
else:
return z_med
for i in range(image.shape[0]):
for j in range(image.shape[1]):
out_img[i][j] = sub_func(copy, i + board, j + board, origen)
return out_img
def main():
# 读取图像
image = cv.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
gray_image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
# 自适应中值滤波
adaptive_filtered_image = auto_median_filter(gray_image, max_size=7)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv.cvtColor(image, cv.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(adaptive_filtered_image, cmap='gray')
plt.title('Adaptive Median Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(5) 形态学滤波(Morphological Filtering)
形态学滤波通过形态学操作(如腐蚀、膨胀、开运算和闭运算)来处理图像,常用于去噪、边缘检测和形状分析。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def morphological_filter(image, operation='opening', kernel_size=3):
"""
形态学滤波
:param image: 输入图像
:param operation: 操作类型('opening', 'closing', 'erosion', 'dilation')
:param kernel_size: 滤波器大小(奇数)
:return: 处理后的图像
"""
kernel = np.ones((kernel_size, kernel_size), np.uint8)
if operation == 'opening':
filtered_image = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
elif operation == 'closing':
filtered_image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)
elif operation == 'erosion':
filtered_image = cv2.erode(image, kernel)
elif operation == 'dilation':
filtered_image = cv2.dilate(image, kernel)
else:
raise ValueError("Invalid operation. Choose from 'opening', 'closing', 'erosion', 'dilation'.")
return filtered_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 开运算
opening_image = morphological_filter(image, operation='opening', kernel_size=3)
# 闭运算
closing_image = morphological_filter(image, operation='closing', kernel_size=3)
# 腐蚀
erosion_image = morphological_filter(image, operation='erosion', kernel_size=3)
# 膨胀
dilation_image = morphological_filter(image, operation='dilation', kernel_size=3)
# 显示原始图像和处理后的图像
plt.figure(figsize=(12, 8))
plt.subplot(2, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(2, 2, 2)
plt.imshow(cv2.cvtColor(opening_image))
plt.title('Opening Image')
plt.axis('off')
plt.subplot(2, 2, 3)
plt.imshow(cv2.cvtColor(closing_image))
plt.title('Closing Image')
plt.axis('off')
plt.subplot(2, 2, 4)
plt.imshow(cv2.cvtColor(erosion_image))
plt.title('Erosion Image')
plt.axis('off')
plt.tight_layout()
plt.show()
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(dilation_image))
plt.title('Dilation Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
3. 边缘检测(Edge Enhancement)
边缘检测是图像处理中的一个重要技术,用于检测图像中的边缘和轮廓。
(1) Prewitt算子
Prewitt算子是一种简单的梯度算子,用于计算图像的梯度幅值和方向。Prewitt算子通过两个3x3的卷积核分别计算水平和垂直方向上的梯度。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def prewitt_edge_detection(image):
"""
Prewitt边缘检测
:param image: 输入图像(灰度图像)
:return: 处理后的图像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 定义Prewitt算子的水平和垂直卷积核
prewitt_x = np.array([[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]], dtype=np.float32)
prewitt_y = np.array([[-1, -1, -1],
[0, 0, 0],
[1, 1, 1]], dtype=np.float32)
# 应用卷积核
gradient_x = cv2.filter2D(image, -1, prewitt_x)
gradient_y = cv2.filter2D(image, -1, prewitt_y)
# 计算梯度幅值
gradient_magnitude = np.sqrt(gradient_x**2 + gradient_y**2)
gradient_magnitude = np.clip(gradient_magnitude, 0, 255).astype(np.uint8)
return gradient_magnitude
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# Prewitt边缘检测
prewitt_image = prewitt_edge_detection(image)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(prewitt_image, cmap='gray')
plt.title('Prewitt Edge Detection')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) Roberts算子
Roberts算子是一种简单的梯度算子,用于计算图像的梯度幅值和方向。Roberts算子通过两个2x2的卷积核分别计算水平和垂直方向上的梯度。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def roberts_edge_detection(image):
"""
Roberts边缘检测
:param image: 输入图像(灰度图像)
:return: 处理后的图像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 定义Roberts算子的水平和垂直卷积核
roberts_x = np.array([[1, 0],
[0, -1]], dtype=np.float32)
roberts_y = np.array([[0, 1],
[-1, 0]], dtype=np.float32)
# 应用卷积核
gradient_x = cv2.filter2D(image, -1, roberts_x)
gradient_y = cv2.filter2D(image, -1, roberts_y)
# 计算梯度幅值
gradient_magnitude = np.sqrt(gradient_x ** 2 + gradient_y ** 2)
gradient_magnitude = np.clip(gradient_magnitude, 0, 255).astype(np.uint8)
return gradient_magnitude
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# Roberts边缘检测
roberts_image = roberts_edge_detection(image)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(roberts_image, cmap='gray')
plt.title('Roberts Edge Detection')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(3) Sobel算子
Sobel算子是一种广泛使用的梯度算子,用于计算图像的梯度幅值和方向。Sobel算子通过两个3x3的卷积核分别计算水平和垂直方向上的梯度。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def sobel_edge_detection(image):
"""
Sobel边缘检测
:param image: 输入图像(灰度图像)
:return: 处理后的图像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 计算水平和垂直方向上的梯度
gradient_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
gradient_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
# 计算梯度幅值
gradient_magnitude = np.sqrt(gradient_x ** 2 + gradient_y ** 2)
gradient_magnitude = np.clip(gradient_magnitude, 0, 255).astype(np.uint8)
return gradient_magnitude
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# Sobel边缘检测
sobel_image = sobel_edge_detection(image)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(sobel_image, cmap='gray')
plt.title('Sobel Edge Detection')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(4) Scharr算子
Scharr算子是Sobel算子的一种改进版本,提供了更高的精度。Scharr算子通过两个3x3的卷积核分别计算水平和垂直方向上的梯度。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def scharr_edge_detection(image):
"""
Scharr边缘检测
:param image: 输入图像(灰度图像)
:return: 处理后的图像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 计算水平和垂直方向上的梯度
gradient_x = cv2.Scharr(image, cv2.CV_64F, 1, 0)
gradient_y = cv2.Scharr(image, cv2.CV_64F, 0, 1)
# 计算梯度幅值
gradient_magnitude = np.sqrt(gradient_x ** 2 + gradient_y ** 2)
gradient_magnitude = np.clip(gradient_magnitude, 0, 255).astype(np.uint8)
return gradient_magnitude
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# Scharr边缘检测
scharr_image = scharr_edge_detection(image)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(scharr_image, cmap='gray')
plt.title('Scharr Edge Detection')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(5) 拉普拉斯算子
拉普拉斯算子是一种二阶导数算子,用于检测图像中的边缘。拉普拉斯算子通过一个3x3的卷积核计算图像的二阶导数。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def laplacian_edge_detection(image):
"""
拉普拉斯边缘检测
:param image: 输入图像(灰度图像)
:return: 处理后的图像
"""
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 应用拉普拉斯算子
laplacian_image = cv2.Laplacian(image, cv2.CV_64F, ksize=3)
# 将结果转换为8位图像
laplacian_image = np.clip(laplacian_image, 0, 255).astype(np.uint8)
return laplacian_image
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 拉普拉斯边缘检测
laplacian_image = laplacian_edge_detection(image)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(laplacian_image, cmap='gray')
plt.title('Laplacian Edge Detection')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(6) Canny边缘检测
Canny边缘检测是一种多阶段的边缘检测算法,能够检测出图像中的强边缘。Canny边缘检测包括以下步骤:
- 高斯滤波:平滑图像,减少噪声。
- 计算梯度幅值和方向:使用Sobel算子计算图像的梯度幅值和方向。
- 非极大值抑制:抑制非极大值像素,保留边缘。
- 双阈值检测:使用高低阈值检测和连接边缘。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def gaussian_blur(image, kernel_size=(5, 5), sigmaX=0):
"""
高斯滤波
:param image: 输入图像
:param kernel_size: 滤波器大小
:param sigmaX: 高斯核的标准差
:return: 处理后的图像
"""
return cv2.GaussianBlur(image, kernel_size, sigmaX)
def compute_gradients(image):
"""
计算图像的梯度幅值和方向
:param image: 输入图像(灰度图像)
:return: 梯度幅值和方向
"""
# 计算水平和垂直方向上的梯度
gradient_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
gradient_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
# 计算梯度幅值
gradient_magnitude = np.sqrt(gradient_x ** 2 + gradient_y ** 2)
gradient_magnitude = np.clip(gradient_magnitude, 0, 255).astype(np.uint8)
# 计算梯度方向
gradient_angle = np.arctan2(gradient_y, gradient_x) * 180 / np.pi
gradient_angle[gradient_angle < 0] += 180
return gradient_magnitude, gradient_angle
def non_max_suppression(gradient_magnitude, gradient_angle):
"""
非极大值抑制
:param gradient_magnitude: 梯度幅值
:param gradient_angle: 梯度方向
:return: 抑制后的梯度幅值
"""
M, N = gradient_magnitude.shape
suppressed = np.zeros((M, N), dtype=np.uint8)
for i in range(1, M-1):
for j in range(1, N-1):
angle = gradient_angle[i, j]
if (0 <= angle < 22.5) or (157.5 <= angle <= 180):
q = gradient_magnitude[i, j+1]
r = gradient_magnitude[i, j-1]
elif (22.5 <= angle < 67.5):
q = gradient_magnitude[i+1, j-1]
r = gradient_magnitude[i-1, j+1]
elif (67.5 <= angle < 112.5):
q = gradient_magnitude[i+1, j]
r = gradient_magnitude[i-1, j]
elif (112.5 <= angle < 157.5):
q = gradient_magnitude[i-1, j-1]
r = gradient_magnitude[i+1, j+1]
if (gradient_magnitude[i, j] >= q) and (gradient_magnitude[i, j] >= r):
suppressed[i, j] = gradient_magnitude[i, j]
else:
suppressed[i, j] = 0
return suppressed
def double_thresholding(suppressed, low_threshold, high_threshold):
"""
双阈值检测
:param suppressed: 抑制后的梯度幅值
:param low_threshold: 低阈值
:param high_threshold: 高阈值
:return: 边缘图像
"""
M, N = suppressed.shape
strong = np.zeros((M, N), dtype=np.uint8)
weak = np.zeros((M, N), dtype=np.uint8)
strong_i, strong_j = np.where(suppressed >= high_threshold)
weak_i, weak_j = np.where((suppressed >= low_threshold) & (suppressed < high_threshold))
strong[strong_i, strong_j] = 255
weak[weak_i, weak_j] = 50
return strong, weak
def edge_tracking(strong, weak):
"""
边缘跟踪
:param strong: 强边缘图像
:param weak: 弱边缘图像
:return: 最终的边缘图像
"""
M, N = strong.shape
final_edges = np.zeros((M, N), dtype=np.uint8)
final_edges[np.where(strong == 255)] = 255
def dfs(i, j):
if i < 0 or i >= M or j < 0 or j >= N:
return
if weak[i, j] == 50:
final_edges[i, j] = 255
weak[i, j] = 0
dfs(i-1, j)
dfs(i+1, j)
dfs(i, j-1)
dfs(i, j+1)
dfs(i-1, j-1)
dfs(i-1, j+1)
dfs(i+1, j-1)
dfs(i+1, j+1)
for i in range(M):
for j in range(N):
if strong[i, j] == 255:
dfs(i, j)
return final_edges
def canny_edge_detection(image, low_threshold=50, high_threshold=150, kernel_size=(5, 5), sigmaX=0):
"""
Canny边缘检测
:param image: 输入图像(灰度图像)
:param low_threshold: 低阈值
:param high_threshold: 高阈值
:param kernel_size: 高斯滤波器大小
:param sigmaX: 高斯核的标准差
:return: 边缘图像
"""
# 1. 高斯滤波
blurred_image = gaussian_blur(image, kernel_size, sigmaX)
# 2. 计算梯度幅值和方向
gradient_magnitude, gradient_angle = compute_gradients(blurred_image)
# 3. 非极大值抑制
suppressed = non_max_suppression(gradient_magnitude, gradient_angle)
# 4. 双阈值检测
strong, weak = double_thresholding(suppressed, low_threshold, high_threshold)
# 5. 边缘跟踪
final_edges = edge_tracking(strong, weak)
return final_edges
def main():
# 读取图像
image = cv2.imread('demo.jpg')
if image is None:
print("Error: Could not read image.")
return
# 转换为灰度图像
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Canny边缘检测
canny_image = canny_edge_detection(gray_image, low_threshold=50, high_threshold=150)
# 显示原始图像和处理后的图像
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(canny_image, cmap='gray')
plt.title('Canny Edge Detection')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
五、频率域(增强)
在图像处理中,频率域增强方法通过将图像转换到频率域,通过修改频率分量来增强图像中的特定特征,再将其转换回空间域得到增强效果。常见的频率域增强方法包括滤波和频谱调整,如低通滤波、高通滤波、带通滤波等。
以下是频率域增强方法的主要步骤:
(1) 傅里叶变换:使用傅里叶变换将空间域图像转换到频率域。
(2) 滤波器设计:根据需要增强的特征(如边缘或噪声),设计频域滤波器。
- 低通滤波器:保留低频成分,抑制高频成分,用于去噪或平滑处理。
- 高通滤波器:保留高频成分,抑制低频成分,用于边缘增强。
- 带通滤波器:保留特定频率区间的成分,适用于增强特定频率范围的细节。
(3) 频谱滤波:将设计好的滤波器应用于频率域图像。
(4) 逆傅里叶变换:将处理后的频率域图像转换回空间域,得到增强后的图像。
1. 傅里叶变换(Fourier Transform)
傅里叶变换是一种将时域信号转换到频域的方法。在图像处理中,傅里叶变换将空间域图像转换到频率域,使得图像的频率成分更加直观。通过傅里叶变换,可以分析图像的频率特性,从而进行图像增强、去噪等处理。
其基本思想是将一个信号分解为多个正弦波和余弦波的组合。
对于一个连续函数f(x),其傅里叶变换F(u)可以表示为:
其中,j是虚数单位,u是频率变量。
对于离散信号f(x),其离散傅里叶变换DFT可以表示为:
其中,N是信号的长度。
1. 快速傅里叶变换(Fast Fourier Transform, FFT)
快速傅里叶变换是一种高效的傅里叶变换算法,能够快速计算离散傅里叶变换。FFT通过将DFT分解为多个小的DFT计算,从而大大减少了计算复杂度。
2. 离散傅里叶变换(Discrete Fourier Transform, DFT)
离散傅里叶变换是傅里叶变换的离散版本,适用于数字图像处理。DFT将离散的图像信号转换为离散的频率信号。
3. 傅里叶逆变换(Inverse Fourier Transform)
傅里叶逆变换将频率域图像转换回空间域。对于离散傅里叶变换,其逆变换可以表示为:
import cv2
import numpy as np
import matplotlib.pyplot as plt
def fft_transform(image):
"""
傅里叶变换
:param image: 输入图像(灰度图像)
:return: 频率域图像
"""
# 计算傅里叶变换
f = np.fft.fft2(image)
# 将零频率分量移到频谱中心
fshift = np.fft.fftshift(f)
return fshift
def ifft_transform(fshift):
"""
傅里叶逆变换
:param fshift: 频率域图像
:return: 空间域图像
"""
# 将零频率分量移到频谱边缘
f_ishift = np.fft.ifftshift(fshift)
# 计算逆傅里叶变换
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)
return img_back
def main():
# 读取图像
image = cv2.imread('demo.jpg', cv2.IMREAD_GRAYSCALE)
if image is None:
print("Error: Could not read image.")
return
# 傅里叶变换
fshift = fft_transform(image)
# 显示原始图像和频谱图像
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(np.log(cv2.magnitude(fshift.real, fshift.imag)), cmap='gray')
plt.title('Magnitude Spectrum')
plt.axis('off')
plt.tight_layout()
plt.show()
# 傅里叶逆变换
img_back = ifft_transform(fshift)
# 显示逆傅里叶变换后的图像
plt.figure(figsize=(8, 4))
plt.imshow(img_back, cmap='gray')
plt.title('Inverse Fourier Transform')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
4. 滤波器设计
(1) 低通滤波
低通滤波器保留图像的低频成分,抑制高频成分。低频成分通常对应于图像的平滑部分,如背景和大尺度结构,而高频成分对应于图像的细节和噪声。因此,低通滤波可以用于图像平滑和去噪。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def fft_transform(image):
"""
傅里叶变换
:param image: 输入图像(灰度图像)
:return: 频率域图像
"""
# 计算傅里叶变换
f = np.fft.fft2(image)
# 将零频率分量移到频谱中心
fshift = np.fft.fftshift(f)
return fshift
def ifft_transform(fshift):
"""
傅里叶逆变换
:param fshift: 频率域图像
:return: 空间域图像
"""
# 将零频率分量移到频谱边缘
f_ishift = np.fft.ifftshift(fshift)
# 计算逆傅里叶变换
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)
return img_back
def low_pass_filter(fshift, d0=30):
"""
低通滤波器
:param fshift: 频率域图像
:param d0: 截止频率
:return: 滤波后的频率域图像
"""
rows, cols = fshift.shape
crow, ccol = rows // 2, cols // 2
mask = np.zeros((rows, cols), np.uint8)
cv2.circle(mask, (ccol, crow), d0, 1, -1)
fshift_filtered = fshift * mask
return fshift_filtered
def main():
# 读取图像
image = cv2.imread('demo.jpg', cv2.IMREAD_GRAYSCALE)
if image is None:
print("Error: Could not read image.")
return
# 傅里叶变换
fshift = fft_transform(image)
# 低通滤波
fshift_lowpass = low_pass_filter(fshift, d0=30)
img_lowpass = ifft_transform(fshift_lowpass)
# 显示原始图像、频谱图像和低通滤波结果
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(img_lowpass, cmap='gray')
plt.title('Low-pass Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) 高通滤波(High-pass Filtering)
高通滤波器保留图像的高频成分,抑制低频成分。高频成分通常对应于图像的细节和边缘,而低频成分对应于图像的平滑部分。因此,高通滤波可以用于边缘检测和细节增强。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def fft_transform(image):
"""
傅里叶变换
:param image: 输入图像(灰度图像)
:return: 频率域图像
"""
# 计算傅里叶变换
f = np.fft.fft2(image)
# 将零频率分量移到频谱中心
fshift = np.fft.fftshift(f)
return fshift
def ifft_transform(fshift):
"""
傅里叶逆变换
:param fshift: 频率域图像
:return: 空间域图像
"""
# 将零频率分量移到频谱边缘
f_ishift = np.fft.ifftshift(fshift)
# 计算逆傅里叶变换
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)
return img_back
def low_pass_filter(fshift, d0=30):
"""
低通滤波器
:param fshift: 频率域图像
:param d0: 截止频率
:return: 滤波后的频率域图像
"""
rows, cols = fshift.shape
crow, ccol = rows // 2, cols // 2
mask = np.zeros((rows, cols), np.uint8)
cv2.circle(mask, (ccol, crow), d0, 1, -1)
fshift_filtered = fshift * mask
return fshift_filtered
def main():
# 读取图像
image = cv2.imread('demo.jpg', cv2.IMREAD_GRAYSCALE)
if image is None:
print("Error: Could not read image.")
return
# 傅里叶变换
fshift = fft_transform(image)
# 低通滤波
fshift_lowpass = low_pass_filter(fshift, d0=30)
img_lowpass = ifft_transform(fshift_lowpass)
# 显示原始图像、频谱图像和低通滤波结果
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(img_lowpass, cmap='gray')
plt.title('Low-pass Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(2) 带通滤波(Band-pass Filtering)
带通滤波器保留图像中特定频率范围内的成分,抑制低于和高于该频率范围的成分。带通滤波可以用于提取特定频率范围内的细节,常用于图像的特定特征增强。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def fft_transform(image):
"""
傅里叶变换
:param image: 输入图像(灰度图像)
:return: 频率域图像
"""
# 计算傅里叶变换
f = np.fft.fft2(image)
# 将零频率分量移到频谱中心
fshift = np.fft.fftshift(f)
return fshift
def ifft_transform(fshift):
"""
傅里叶逆变换
:param fshift: 频率域图像
:return: 空间域图像
"""
# 将零频率分量移到频谱边缘
f_ishift = np.fft.ifftshift(fshift)
# 计算逆傅里叶变换
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)
return img_back
def high_pass_filter(fshift, d0=30):
"""
高通滤波器
:param fshift: 频率域图像
:param d0: 截止频率
:return: 滤波后的频率域图像
"""
rows, cols = fshift.shape
crow, ccol = rows // 2, cols // 2
mask = np.ones((rows, cols), np.uint8)
cv2.circle(mask, (ccol, crow), d0, 0, -1)
fshift_filtered = fshift * mask
return fshift_filtered
def main():
# 读取图像
image = cv2.imread('demo.jpg', cv2.IMREAD_GRAYSCALE)
if image is None:
print("Error: Could not read image.")
return
# 傅里叶变换
fshift = fft_transform(image)
# 高通滤波
fshift_highpass = high_pass_filter(fshift, d0=30)
img_highpass = ifft_transform(fshift_highpass)
# 显示原始图像、频谱图像和高通滤波结果
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(img_highpass, cmap='gray')
plt.title('High-pass Filtered Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
(3) 小波变换(Wavelet Transform)
小波变换是一种将信号分解为不同尺度和位置的成分的方法。与傅里叶变换不同,小波变换能够提供时间和频率的局部化信息。
import cv2
import numpy as np
import matplotlib.pyplot as plt
import pywt
def dwt_transform(image, wavelet='haar', level=1):
"""
离散小波变换
:param image: 输入图像(灰度图像)
:param wavelet: 小波类型
:param level: 分解层数
:return: 分解后的系数
"""
coeffs = pywt.wavedec2(image, wavelet, level=level)
return coeffs
def idwt_transform(coeffs, wavelet='haar'):
"""
离散小波逆变换
:param coeffs: 分解后的系数
:param wavelet: 小波类型
:return: 重构后的图像
"""
reconstructed_image = pywt.waverec2(coeffs, wavelet)
return reconstructed_image
def main():
# 读取图像
image = cv2.imread('demo.jpg', cv2.IMREAD_GRAYSCALE)
if image is None:
print("Error: Could not read image.")
return
# 离散小波变换
coeffs = dwt_transform(image, wavelet='haar', level=1)
LL, (LH, HL, HH) = coeffs
# 显示原始图像和分解后的系数
plt.figure(figsize=(12, 6))
plt.subplot(2, 2, 1)
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.subplot(2, 2, 2)
plt.imshow(LL, cmap='gray')
plt.title('LL (Approximation)')
plt.axis('off')
plt.subplot(2, 2, 3)
plt.imshow(LH, cmap='gray')
plt.title('LH (Horizontal Detail)')
plt.axis('off')
plt.subplot(2, 2, 4)
plt.imshow(HL, cmap='gray')
plt.title('HL (Vertical Detail)')
plt.axis('off')
plt.tight_layout()
plt.show()
plt.figure(figsize=(8, 4))
plt.subplot(1, 2, 1)
plt.imshow(HH, cmap='gray')
plt.title('HH (Diagonal Detail)')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(idwt_transform(coeffs, wavelet='haar'), cmap='gray')
plt.title('Reconstructed Image')
plt.axis('off')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()