loading

【图像处理基石】图像预处理方面有哪些经典的算法?

  • Home
  • Blog
  • 【图像处理基石】图像预处理方面有哪些经典的算法?

【图像处理基石】图像预处理方面有哪些经典的算法?

图像预处理是计算机视觉任务(如目标检测、图像分割、人脸识别)的基础步骤,核心目的是消除图像中的噪声、提升对比度、修正几何畸变等,为后续高阶处理提供高质量输入。以下先系统梳理经典算法,再通过Python实现2个高频应用算法(直方图均衡化、中值滤波)。

一、图像预处理经典算法梳理

根据处理目标,可将经典算法分为5大类,每类包含核心算法、原理、目的及应用场景:

1. 几何变换类(修正空间畸变)

针对图像的空间位置或形状偏差,调整像素坐标以满足后续对齐、裁剪等需求。

算法

原理

核心目的

应用场景

平移

对所有像素按指定偏移量(dx, dy)移动,公式:(x', y') = (x+dx, y+dy)

调整图像位置

图像拼接、目标定位校准

旋转

以某点(如中心)为原点,按角度θ旋转,需处理像素插值避免模糊

修正图像倾斜

文档扫描(矫正倾斜文字)

缩放

按比例(fx, fy)放大/缩小像素,常用双线性插值提升画质

统一图像尺寸

神经网络输入标准化(如224x224)

翻转

水平翻转(左右镜像)或垂直翻转(上下镜像)

数据增强、修正视角

人脸识别(增加样本多样性)

2. 图像增强类(提升视觉质量)

通过调整像素灰度/颜色分布,增强图像的细节对比度,解决低光照、模糊等问题。

算法

原理

核心目的

应用场景

全局直方图均衡化

拉伸像素灰度分布,使直方图趋于均匀(映射灰度累积概率)

提升整体对比度

医学图像(如X光片)、低光照片

CLAHE(自适应直方图均衡化)

将图像分块,对每块单独均衡化,限制对比度避免过增强

增强局部细节(如暗区)

逆光照片、监控图像

伽马校正

通过幂函数(O = I^γ)调整灰度:γ<1提亮,γ>1压暗

修正光照不均

显示器校准、水下图像增强

对比度拉伸(线性变换)

线性映射灰度范围:O = a*I + b(a>1增强对比度,a<1降低)

扩展有效灰度区间

灰度范围狭窄的图像(如雾天图)

3. 图像去噪类(消除干扰像素)

针对图像采集过程中的噪声(如椒盐噪声、高斯噪声),通过邻域像素平滑实现去噪。

算法

原理

核心目的

应用场景

均值滤波

用邻域内所有像素的平均值替换中心像素

消除高斯噪声

轻微模糊的自然图像

中值滤波

用邻域内像素的中值替换中心像素

消除椒盐噪声(脉冲噪声)

老照片、传感器噪声图像

高斯滤波

用高斯核(权重随距离递减)加权平均邻域像素

平滑图像、保留细节

预处理(如边缘检测前去噪)

双边滤波

结合空间距离(邻域权重)和灰度相似度(避免模糊边缘)加权平均

去噪+保留边缘

人像美颜、纹理保留

4. 颜色空间转换(适配任务需求)

将图像从默认的RGB空间转换为其他空间,简化后续处理(如分离亮度与色彩)。

转换方向

原理

核心目的

应用场景

RGB → 灰度

加权平均RGB通道:Gray = 0.299R + 0.587G + 0.114B(符合人眼感知)

减少维度(3→1)

灰度图像任务(如文字识别)

RGB → HSV

分离色调(H)、饱和度(S)、亮度(V)通道

单独调整亮度/色彩

图像增强、色彩分割

RGB → YCrCb

分离亮度(Y)与色差(Cr/Cb)通道

视频压缩、肤色检测

人脸识别(肤色区域提取)

5. 阈值处理(二值化分割)

将灰度图转换为二值图(仅黑白两色),突出目标区域。

算法

原理

核心目的

应用场景

全局阈值

用固定阈值T分割:I>T设为255(白),否则设为0(黑)(如Otsu自动选T)

简单目标分割

文字提取、硬币检测

自适应阈值

按局部区域动态计算阈值(如邻域均值)

处理光照不均图像

文档扫描(文字与背景分离)

二、Python实现经典算法(2个高频案例)

以下基于 OpenCV(图像处理库) 和 Matplotlib(图像显示库) 实现,需先安装依赖:

bash

复制代码

pip install opencv-python numpy matplotlib

案例1:直方图均衡化(全局+CLAHE)

需求:提升低对比度图像的细节(如逆光照片),对比全局均衡化与CLAHE的效果差异。

实现步骤:

加载图像并转换为灰度图(均衡化通常在单通道上进行);

实现全局直方图均衡化;

实现CLAHE(自适应均衡化);

显示原图、全局均衡化图、CLAHE图及对应直方图。

代码:

python

复制代码

import cv2

import numpy as np

import matplotlib.pyplot as plt

# 1. 加载图像(以灰度模式读取,0表示灰度)

img = cv2.imread("low_contrast_image.jpg", 0) # 替换为你的图像路径

if img is None:

raise ValueError("图像加载失败,请检查路径是否正确!")

# 2. 全局直方图均衡化

global_eq = cv2.equalizeHist(img)

# 3. CLAHE(自适应直方图均衡化)

clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) # clipLimit限制对比度,tileGridSize分块大小

clahe_eq = clahe.apply(img)

# 4. 计算各图像的直方图(用于对比)

def calculate_histogram(image):

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

return hist / hist.sum() # 归一化,便于显示

hist_original = calculate_histogram(img)

hist_global = calculate_histogram(global_eq)

hist_clahe = calculate_histogram(clahe_eq)

# 5. 显示结果(Matplotlib默认RGB,灰度图直接显示)

plt.figure(figsize=(15, 10))

# 图像显示

plt.subplot(2, 3, 1)

plt.imshow(img, cmap="gray")

plt.title("原图")

plt.axis("off")

plt.subplot(2, 3, 2)

plt.imshow(global_eq, cmap="gray")

plt.title("全局直方图均衡化")

plt.axis("off")

plt.subplot(2, 3, 3)

plt.imshow(clahe_eq, cmap="gray")

plt.title("CLAHE(自适应均衡化)")

plt.axis("off")

# 直方图显示

plt.subplot(2, 3, 4)

plt.plot(hist_original, color="black")

plt.title("原图直方图")

plt.xlabel("灰度值")

plt.ylabel("概率密度")

plt.subplot(2, 3, 5)

plt.plot(hist_global, color="black")

plt.title("全局均衡化直方图")

plt.xlabel("灰度值")

plt.subplot(2, 3, 6)

plt.plot(hist_clahe, color="black")

plt.title("CLAHE直方图")

plt.xlabel("灰度值")

plt.tight_layout()

plt.show()

结果分析:

全局均衡化:整体对比度提升,但可能导致局部过亮(如天空区域泛白);

CLAHE:通过分块均衡化,在提升暗区细节(如建筑阴影)的同时,避免过增强,效果更自然。

案例2:中值滤波(消除椒盐噪声)

需求:去除图像中的椒盐噪声(随机黑白斑点),对比原图与去噪后的效果。

实现步骤:

加载灰度图并手动添加椒盐噪声(模拟真实噪声场景);

用中值滤波处理噪声图像;

对比原图、噪声图、去噪图。

代码:

python

复制代码

import cv2

import numpy as np

import matplotlib.pyplot as plt

# 1. 加载灰度图像

img = cv2.imread("lena.jpg", 0) # 替换为你的图像路径(如经典Lena图)

if img is None:

raise ValueError("图像加载失败,请检查路径是否正确!")

# 2. 手动添加椒盐噪声(噪声比例:10%)

def add_salt_pepper_noise(image, noise_ratio=0.1):

h, w = image.shape

noise_img = image.copy()

# 计算噪声像素数量

noise_pixels = int(h * w * noise_ratio)

# 添加盐噪声(白色斑点,灰度255)

for _ in range(noise_pixels // 2):

x = np.random.randint(0, w)

y = np.random.randint(0, h)

noise_img[y, x] = 255

# 添加椒噪声(黑色斑点,灰度0)

for _ in range(noise_pixels // 2):

x = np.random.randint(0, w)

y = np.random.randint(0, h)

noise_img[y, x] = 0

return noise_img

noise_img = add_salt_pepper_noise(img, noise_ratio=0.1)

# 3. 中值滤波处理(核大小为3x3,需为奇数)

median_filtered = cv2.medianBlur(noise_img, ksize=3) # ksize可调整为5、7(核越大去噪越强,但细节越模糊)

# 4. 显示结果

plt.figure(figsize=(12, 4))

plt.subplot(1, 3, 1)

plt.imshow(img, cmap="gray")

plt.title("原图")

plt.axis("off")

plt.subplot(1, 3, 2)

plt.imshow(noise_img, cmap="gray")

plt.title("添加椒盐噪声(10%)")

plt.axis("off")

plt.subplot(1, 3, 3)

plt.imshow(median_filtered, cmap="gray")

plt.title("中值滤波(3x3核)")

plt.axis("off")

plt.tight_layout()

plt.show()

结果分析:

噪声图:出现明显的黑白斑点(椒盐噪声),细节被掩盖;

中值滤波后:大部分噪声被消除,图像细节(如面部轮廓、眼睛)保留较好,这是因为中值对脉冲噪声的抑制效果优于均值滤波。

三、总结

图像预处理算法的选择需结合具体任务和图像问题:

若图像对比度低:优先用CLAHE(优于全局均衡化);

若图像有椒盐噪声:优先用中值滤波(核大小根据噪声强度调整);

若需统一图像尺寸:用缩放(双线性插值);

若需分离亮度与色彩:将RGB转为HSV或YCrCb。

上述实现的2个算法是工业界最常用的预处理步骤,可直接集成到目标检测、图像分割等 pipeline 中,提升后续模型的精度。