首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >图像预处理-最全总结

图像预处理-最全总结

作者头像
啊阿狸不会拉杆
发布2026-01-21 13:40:28
发布2026-01-21 13:40:28
2220
举报

在计算机视觉领域,图像预处理是连接原始图像与高阶任务(如目标检测、图像分类、语义分割)的关键桥梁。原始图像往往存在噪声、光照不均、尺寸不一等问题,直接影响后续算法的效果。本文系统整理了六大类核心预处理操作,涵盖像素调整、几何变换、噪声处理等,所有操作均提供可直接复用的Python 实现,适合新手入门。

一、图像预处理核心模块思维导图

二、图像预处理一般流程

三、核心操作详解

(一)像素值调整类:优化图像基础属性

像素是图像的基本单元,调整像素值可直接改善图像的视觉质量和数据分布,为后续处理减少干扰。

1. 二值化

将图像转换为仅含黑白两种颜色的二值图像(像素值 0 或 255),通过设定阈值区分前景(如文字、目标)和背景。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'aali4.jpg'

# --- 主程序 ---
def main():
    # 1. 读取图像并转为灰度
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return
    gray_img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

    # 2. 执行二值化 (使用Otsu's方法自动寻找最优阈值)
    # THRESH_BINARY: 高于阈值为255,低于为0
    # THRESH_OTSU: 自动计算阈值
    _, binarized_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    # 3. 显示结果
    plt.figure(figsize=(10, 5))
    plt.subplot(121)
    plt.imshow(gray_img, cmap='gray')
    plt.title("灰度原图")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(binarized_img, cmap='gray')
    plt.title("二值化结果 (Otsu)")
    plt.axis('off')
    plt.tight_layout()
    plt.show()

if __name__ == '__main__':
    main()

应用场景:文字识别、条形码提取、轮廓分割(消除灰度渐变干扰)。

2. 灰度化

将 RGB 三通道彩色图像转换为单通道灰度图(像素值 0-255),通过加权平均三通道值实现(如:Gray=0.299R + 0.587G + 0.114*B)。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
# 图像文件名
IMAGE_FILENAME = 'ALi.jpg'

# --- 主程序 ---
def main():
    # 1. 读取图像
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。请检查文件名和路径。")
        return

    # 2. 执行灰度化
    # 使用cv2.COLOR_BGR2GRAY将BGR图像转换为灰度图
    gray_img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

    # 3. 显示结果
    plt.figure(figsize=(10, 5))
    plt.subplot(121)
    plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
    plt.title("原始图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(gray_img, cmap='gray')
    plt.title("灰度化结果")
    plt.axis('off')
    plt.tight_layout()
    plt.show()

if __name__ == '__main__':
    main()

核心价值:减少 2/3 的数据量,同时保留图像轮廓特征,是多数算法(如边缘检测)的前置步骤。

3. 归一化

将像素值映射到固定区间(如 [0,1] 或 [-1,1]),解决不同图像像素范围差异(如有的 0-255,有的 0-1023)。

代码语言:javascript
复制
import cv2
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'aali2.jpg'

# --- 主程序 ---
def main():
    # 1. 读取图像并转为灰度
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return
    gray_img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

    # 2. 执行归一化 (Min-Max Scaling)
    # 将数据类型转为float32以进行计算
    img_float = gray_img.astype(np.float32)
    # 应用公式: (x - min) / (max - min)
    normalized_img = (img_float - np.min(img_float)) / (np.max(img_float) - np.min(img_float) + 1e-10)

    # 3. 显示结果
    plt.figure(figsize=(10, 5))
    plt.subplot(121)
    plt.imshow(gray_img, cmap='gray')
    plt.title("灰度原图")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(normalized_img, cmap='gray')
    plt.title("归一化结果 (0-1)")
    plt.axis('off')
    plt.tight_layout()
    plt.show()

if __name__ == '__main__':
    main()

作用:避免因像素值范围不一致导致模型收敛困难(如神经网络输入需标准化)。

4. 对比度增强

通过拉伸或压缩像素值分布范围(如直方图均衡化),扩大明暗区域差异。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'XiaoYan.jpg'

# --- 主程序 ---
def main():
    # 1. 读取图像并转为灰度
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return
    gray_img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

    # 2. 执行对比度增强 (使用CLAHE方法)
    # 创建CLAHE对象,clipLimit控制对比度增强程度
    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
    enhanced_img = clahe.apply(gray_img)

    # 3. 显示结果
    plt.figure(figsize=(10, 6))
    plt.subplot(121)
    plt.imshow(gray_img, cmap='gray')
    plt.title("灰度原图")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(enhanced_img, cmap='gray')
    plt.title("对比度增强结果 (CLAHE)")
    plt.axis('off')
    plt.tight_layout()
    plt.show()

if __name__ == '__main__':
    main()

效果:让暗部细节变清晰(如逆光照片),亮部不过曝。

(二)几何变换类:调整图像空间形态

几何变换不改变像素颜色,仅调整像素的空间位置,解决图像尺寸不统一、角度偏差等问题。

1. 调整大小

按比例或固定尺寸缩放图像(如将 1024x768 缩放到 224x224 适配 CNN 输入),常用双线性插值(平衡速度与效果)。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'aali2.jpg'
NEW_WIDTH = 50  # 目标宽度


# --- 主程序 ---
def main():
    # 1. 读取图像
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。请检查文件名和路径。")
        return

    # 2. 计算新高度以保持宽高比
    height, width = img_bgr.shape[:2]
    ratio = NEW_WIDTH / width
    new_height = int(height * ratio)

    # 3. 执行调整大小
    # 使用双线性插值(INTER_LINEAR),在速度和质量之间取得平衡
    resized_img = cv2.resize(img_bgr, (NEW_WIDTH, new_height), interpolation=cv2.INTER_LINEAR)

    # 4. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
    plt.title(f"原始图像 (W: {width}, H: {height})")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(cv2.cvtColor(resized_img, cv2.COLOR_BGR2RGB))
    plt.title(f"调整大小后 (W: {NEW_WIDTH}, H: {new_height})")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()

注意:等比例缩放避免目标变形(如人脸拉伸)。

2. 翻转

包括水平翻转(左右镜像)和垂直翻转(上下颠倒),操作简单但能有效增加样本多样性。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'TianHuoSanXuanBian.png'
# 翻转方式: 1=水平翻转, 0=垂直翻转, -1=水平垂直同时翻转
FLIP_CODE = 1


# --- 主程序 ---
def main():
    # 1. 读取图像
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return

    # 2. 执行翻转
    flipped_img = cv2.flip(img_bgr, FLIP_CODE)

    # 3. 确定翻转方向的文字描述
    flip_direction = "水平" if FLIP_CODE == 1 else ("垂直" if FLIP_CODE == 0 else "水平和垂直")

    # 4. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
    plt.title("原始图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(cv2.cvtColor(flipped_img, cv2.COLOR_BGR2RGB))
    plt.title(f"{flip_direction}翻转后")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()

应用:数据增强(如训练集加入翻转图像,提升模型对方向的鲁棒性)。

3. 旋转

围绕中心或指定点旋转任意角度(如 90°、45°),需处理旋转后空白区域(常用填充背景色或边缘像素)。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'aali5.jpg'
ROTATION_ANGLE = 180  # 旋转角度(正数为逆时针,负数为顺时针)


# --- 主程序 ---
def main():
    # 1. 读取图像
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return

    # 2. 获取图像中心和尺寸
    height, width = img_bgr.shape[:2]
    center = (width // 2, height // 2)

    # 3. 获取旋转矩阵
    # getRotationMatrix2D(center, angle, scale)
    rotation_matrix = cv2.getRotationMatrix2D(center, ROTATION_ANGLE, 1.0)

    # 4. 执行旋转
    # warpAffine会自动处理旋转后图像的大小,并用黑色填充空白区域
    rotated_img = cv2.warpAffine(img_bgr, rotation_matrix, (width, height))

    # 5. 显示结果
    plt.figure(figsize=(12, 8))

    plt.subplot(121)
    plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
    plt.title("原始图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(cv2.cvtColor(rotated_img, cv2.COLOR_BGR2RGB))
    plt.title(f"旋转 {ROTATION_ANGLE} 度后")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()

场景:修正倾斜图像(如扫描文档的歪斜)。

4. 裁剪

从图像中提取感兴趣区域(ROI),如从身份证照片中裁剪出头像区域。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'aali4.jpg'
# 定义裁剪区域的坐标 (y1, y2, x1, x2)
# 请根据您的图像内容修改这些值
CROP_REGION = (400, 800, 200, 400)  # (左上角y, 右下角y, 左上角x, 右下角x)


# --- 主程序 ---
def main():
    # 1. 读取图像
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return

    y1, y2, x1, x2 = CROP_REGION

    # 2. 执行裁剪 (NumPy数组切片)
    # 注意OpenCV的坐标顺序是 [y, x]
    cropped_img = img_bgr[y1:y2, x1:x2]

    # 3. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
    # 在原图上用红色方框标记出裁剪区域
    rect = plt.Rectangle((x1, y1), x2 - x1, y2 - y1, fill=False, edgecolor='red', linewidth=2)
    plt.gca().add_patch(rect)
    plt.title("原始图像 (红框为裁剪区域)")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(cv2.cvtColor(cropped_img, cv2.COLOR_BGR2RGB))
    plt.title("裁剪后图像")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()

优势:去除冗余信息,聚焦核心目标,减少算法计算量。

5. 几何校正

修正因拍摄角度导致的畸变(如透视畸变:矩形拍成长梯形),通过透视变换还原真实形状。

代码语言:javascript
复制
import cv2
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'ALi5.jpg'
# 定义源图像中待校正物体的四个顶点坐标 (顺时针或逆时针顺序)
# 【重要】请根据您的图像,手动修改这些坐标点!
# 示例:假设是一个倾斜的矩形物体
src_points = np.float32([[700, 500], [1000, 400], [1000, 900],[650, 1070]])

# 定义目标图像中四个顶点的对应坐标 (通常是一个规则的矩形)
width = 300
height = 250
dst_points = np.float32([[0, 0], [width, 0], [width, height], [0, height]])


# --- 主程序 ---
def main():
    # 1. 读取图像
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return

    # 2. 计算透视变换矩阵
    matrix = cv2.getPerspectiveTransform(src_points, dst_points)

    # 3. 执行透视变换
    corrected_img = cv2.warpPerspective(img_bgr, matrix, (width, height))

    # 4. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    img_with_points = img_bgr.copy()
    # 在原图上绘制源点,方便验证
    for point in src_points:
        cv2.circle(img_with_points, (int(point[0]), int(point[1])), 5, (0, 0, 255), -1)
    plt.imshow(cv2.cvtColor(img_with_points, cv2.COLOR_BGR2RGB))
    plt.title("原始图像 (红点为校正参考点)")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(cv2.cvtColor(corrected_img, cv2.COLOR_BGR2RGB))
    plt.title("几何校正后图像")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()

典型案例:扫描文档校正、车牌倾斜修正。

(三)噪声处理类:提升图像纯净度

原始图像易受传感器、环境干扰产生噪声(如低光拍摄的雪花噪点),噪声会掩盖细节,需针对性去除。

1. 高斯滤波去噪

用高斯核(中间值大、边缘值小的矩阵)与图像卷积,平滑像素突变,适合去除高斯噪声(分布符合正态分布的噪声)。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'bird.jpg'
KERNEL_SIZE = (17, 17)  # 高斯核大小,必须是正的奇数


# --- 主程序 ---
def main():
    # 1. 读取图像并转为灰度
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return
    gray_img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

    # 2. 执行高斯滤波去噪
    # GaussianBlur(src, ksize, sigmaX)
    # sigmaX: X方向的高斯核标准差,0表示由ksize自动计算
    denoised_img = cv2.GaussianBlur(gray_img, KERNEL_SIZE, 0)

    # 3. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(gray_img, cmap='gray')
    plt.title("原始灰度图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(denoised_img, cmap='gray')
    plt.title(f"高斯滤波去噪后 (核大小: {KERNEL_SIZE})")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()

特点:平滑效果柔和,但可能模糊边缘。

2. 均值滤波去噪

用邻域像素的平均值替换当前像素,简单高效,适合去除椒盐噪声(随机出现的黑白点噪声)。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'bird.jpg'
KERNEL_SIZE = 11  # 中值滤波核大小,必须是正的奇数


# --- 主程序 ---
def main():
    # 1. 读取图像并转为灰度
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return
    gray_img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

    # 2. 执行中值滤波去噪
    # medianBlur(src, ksize)
    denoised_img = cv2.medianBlur(gray_img, KERNEL_SIZE)

    # 3. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(gray_img, cmap='gray')
    plt.title("原始灰度图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(denoised_img, cmap='gray')
    plt.title(f"中值滤波去噪后 (核大小: {KERNEL_SIZE})")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()

注意:核越大去噪越强,但细节损失越多。【

3. 去模糊

针对运动模糊(如拍摄移动物体的拖影)或失焦模糊,通过逆滤波、维纳滤波等算法恢复清晰度。

代码语言:javascript
复制
import cv2
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'bird.jpg'
# 假设的模糊核大小,用于生成示例模糊图像
BLUR_KERNEL_SIZE = 15
# 维纳滤波的K值,控制去模糊的强度和对噪声的抑制,值越小去模糊越强,但可能放大噪声
WIENER_K = 0.01


# --- 主程序 ---
def main():
    # 1. 读取图像并转为灰度
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。请检查文件名和路径。")
        return
    gray_img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

    # --- 步骤A: 生成一个模拟的模糊图像 (与之前相同) ---
    print("步骤A: 为演示,生成一个模拟的运动模糊图像...")
    # 创建一个水平方向的运动模糊核
    blur_kernel = np.zeros((BLUR_KERNEL_SIZE, BLUR_KERNEL_SIZE))
    blur_kernel[int((BLUR_KERNEL_SIZE - 1) / 2), :] = 1.0
    blur_kernel = blur_kernel / BLUR_KERNEL_SIZE
    # 应用模糊核
    blurred_img = cv2.filter2D(gray_img, -1, blur_kernel)

    # 为了让效果更真实,我们再加入一点高斯噪声
    noise = np.random.normal(0, 1, blurred_img.shape).astype(np.int16)
    noisy_blurred_img = cv2.add(blurred_img.astype(np.int16), noise).clip(0, 255).astype(np.uint8)

    # --- 步骤B: 使用傅里叶变换手动实现维纳滤波 ---
    print("步骤B: 使用傅里叶变换手动实现维纳滤波...")
    # 获取图像和核的尺寸
    rows, cols = gray_img.shape
    k_rows, k_cols = blur_kernel.shape

    # 1. 对图像和核进行傅里叶变换前的准备
    # 将核的大小调整为与图像一致,并进行中心对齐
    padded_kernel = np.zeros((rows, cols), np.float32)
    padded_kernel[:k_rows, :k_cols] = blur_kernel
    # 将核的中心移动到频域的原点
    padded_kernel = np.fft.fftshift(padded_kernel)

    # 2. 对模糊图像和调整后的核进行傅里叶变换
    fft_blurred = np.fft.fft2(noisy_blurred_img)

    # 3. 在频域中应用维纳滤波
    # 维纳滤波公式: G(u,v) = [H*(u,v) / (|H(u,v)|^2 + K)] * F_blurred(u,v)
    # 其中 H*(u,v) 是H(u,v)的共轭,|H(u,v)|^2 是H(u,v)的模的平方
    fft_kernel = np.fft.fft2(padded_kernel)
    fft_kernel_conj = np.conj(fft_kernel)
    fft_kernel_mag_sq = np.abs(fft_kernel) ** 2

    # 计算维纳滤波的频率响应
    wiener_filter = fft_kernel_conj / (fft_kernel_mag_sq + WIENER_K)

    # 将滤波器应用到模糊图像的频谱上
    fft_deblurred = fft_blurred * wiener_filter

    # 4. 对结果进行逆傅里叶变换,得到去模糊后的图像
    deblurred_img = np.fft.ifft2(fft_deblurred)
    deblurred_img = np.abs(np.fft.ifftshift(deblurred_img))
    deblurred_img = cv2.normalize(deblurred_img, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)

    # --- 步骤C: 显示结果 ---
    print("步骤C: 显示结果...")
    plt.figure(figsize=(18, 6))

    plt.subplot(131)
    plt.imshow(gray_img, cmap='gray')
    plt.title("1. 原始灰度图像")
    plt.axis('off')

    plt.subplot(132)
    plt.imshow(noisy_blurred_img, cmap='gray')
    plt.title("2. 模拟的模糊+噪声图像")
    plt.axis('off')

    plt.subplot(133)
    plt.imshow(deblurred_img, cmap='gray')
    plt.title(f"3. 傅里叶维纳滤波去模糊后 (K={WIENER_K})")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()

难点:需估计模糊核(如运动方向和距离)。

4. 双边滤波

同时考虑空间距离(类似高斯滤波)和像素值差异(保留边缘:边缘处像素值差异大,不被平滑),实现 “去噪 + 保边” 双重效果。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'bird.jpg'
# 注意:双边滤波的核大小通常较小
KERNEL_SIZE = 9
# 色彩空间标准差,值越大,允许更多不同颜色的像素被混合
SIGMA_COLOR = 222
# 坐标空间标准差,值越大,影响范围越广
SIGMA_SPACE = 23


# --- 主程序 ---
def main():
    # 1. 读取图像(保留彩色,双边滤波对彩色图效果更好)
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return

    # 2. 执行双边滤波
    # bilateralFilter(src, d, sigmaColor, sigmaSpace)
    denoised_img = cv2.bilateralFilter(img_bgr, KERNEL_SIZE, SIGMA_COLOR, SIGMA_SPACE)

    # 3. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
    plt.title("原始彩色图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(cv2.cvtColor(denoised_img, cv2.COLOR_BGR2RGB))
    plt.title(f"双边滤波去噪后 (保边)")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()

适用场景:人脸美颜(去噪但保留 facial contour)。

(四)形态学操作类:基于形状的特征优化

形态学操作以 “结构元素”(如 3x3 矩形、十字形)为工具,通过腐蚀、膨胀等组合,提取图像形状特征。

1. 腐蚀

用结构元素遍历图像,仅保留结构元素完全覆盖的前景像素,实现 “收缩前景、去除小噪点”。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'ALi2.jpg'
KERNEL_SIZE = (4, 4)  # 结构元素大小
ITERATIONS = 7  # 腐蚀操作的迭代次数


# --- 主程序 ---
def main():
    # 1. 读取图像并转为灰度
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return
    gray_img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

    # 为了更好地展示效果,先对图像进行二值化处理
    _, binary_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    # 2. 定义结构元素 (Kernel)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, KERNEL_SIZE)

    # 3. 执行腐蚀操作
    eroded_img = cv2.erode(binary_img, kernel, iterations=ITERATIONS)

    # 4. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(binary_img, cmap='gray')
    plt.title("原始二值图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(eroded_img, cmap='gray')
    plt.title(f"腐蚀后 (核大小: {KERNEL_SIZE}, 迭代: {ITERATIONS})")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()

效果:细线条变细,小斑块消失。

2. 膨胀

与腐蚀相反,保留结构元素部分覆盖的前景像素,实现 “扩大前景、连接断裂区域”。

代码语言:javascript
复制
import cv2
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'ALi.jpg'
KERNEL_SIZE = (3, 3)  # 结构元素大小
ITERATIONS = 2  # 膨胀操作的迭代次数


# --- 主程序 ---
def main():
    # 1. 读取图像并转为灰度
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return
    gray_img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

    # 为了更好地展示效果,先对图像进行二值化处理
    _, binary_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    # 2. 定义结构元素 (Kernel)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, KERNEL_SIZE)

    # 3. 执行膨胀操作
    dilated_img = cv2.dilate(binary_img, kernel, iterations=ITERATIONS)

    # 4. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(binary_img, cmap='gray')
    plt.title("原始二值图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(dilated_img, cmap='gray')
    plt.title(f"膨胀后 (核大小: {KERNEL_SIZE}, 迭代: {ITERATIONS})")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()

效果:细线条变粗,缺口被填充。

3. 开运算(先腐蚀后膨胀)

先腐蚀去除小噪点,再膨胀恢复前景形状,适合 “去噪且不改变主体大小”(如去除细胞图像中的杂点)。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'aali4.jpg'
KERNEL_SIZE = (13, 12)  # 结构元素大小


# --- 主程序 ---
def main():
    # 1. 读取图像并转为灰度
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return
    gray_img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

    # 为了更好地展示效果,先对图像进行二值化处理
    _, binary_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    # 2. 定义结构元素 (Kernel)
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, KERNEL_SIZE)

    # 3. 执行开运算
    opened_img = cv2.morphologyEx(binary_img, cv2.MORPH_OPEN, kernel)

    # 4. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(binary_img, cmap='gray')
    plt.title("原始二值图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(opened_img, cmap='gray')
    plt.title(f"开运算后 (核大小: {KERNEL_SIZE})")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()
4. 闭运算(先膨胀后腐蚀)

先膨胀填充小孔洞,再腐蚀恢复前景形状,适合 “填洞且不改变主体大小”(如修复目标内部的空洞)。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'aali4.jpg'
KERNEL_SIZE = (5, 5)  # 结构元素大小


# --- 主程序 ---
def main():
    # 1. 读取图像并转为灰度
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return
    gray_img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

    # 为了更好地展示效果,先对图像进行二值化处理
    _, binary_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    # 2. 定义结构元素 (Kernel)
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, KERNEL_SIZE)

    # 3. 执行闭运算
    closed_img = cv2.morphologyEx(binary_img, cv2.MORPH_CLOSE, kernel)

    # 4. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(binary_img, cmap='gray')
    plt.title("原始二值图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(closed_img, cmap='gray')
    plt.title(f"闭运算后 (核大小: {KERNEL_SIZE})")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()
5. 形态学梯度(膨胀 - 腐蚀)

通过膨胀与腐蚀的差值,提取前景边缘轮廓,比传统边缘检测更清晰(抗噪性强)。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'ALi.jpg'
KERNEL_SIZE = (3, 3)  # 结构元素大小


# --- 主程序 ---
def main():
    # 1. 读取图像并转为灰度
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return
    gray_img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

    # 为了更好地展示效果,先对图像进行二值化处理
    _, binary_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    # 2. 定义结构元素 (Kernel)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, KERNEL_SIZE)

    # 3. 执行形态学梯度运算
    gradient_img = cv2.morphologyEx(binary_img, cv2.MORPH_GRADIENT, kernel)

    # 4. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(binary_img, cmap='gray')
    plt.title("原始二值图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(gradient_img, cmap='gray')
    plt.title(f"形态学梯度 (轮廓) (核大小: {KERNEL_SIZE})")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()
6. 顶帽变换(原始图像 - 开运算结果)

突出比周围亮的小区域(如 X 光片中的亮斑),适合低对比度图像的细节提取。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'aali.jpg'
KERNEL_SIZE = (15, 15)  # 结构元素大小,通常较大以捕捉小物体


# --- 主程序 ---
def main():
    # 1. 读取图像并转为灰度
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return
    gray_img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

    # 为了更好地展示效果,先对图像进行二值化处理
    _, binary_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    # 2. 定义结构元素 (Kernel)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, KERNEL_SIZE)

    # 3. 执行顶帽变换
    top_hat_img = cv2.morphologyEx(binary_img, cv2.MORPH_TOPHAT, kernel)

    # 为了更好地可视化,我们将提取到的区域在原图上标记出来
    highlighted_img = cv2.cvtColor(binary_img, cv2.COLOR_GRAY2BGR)
    highlighted_img[top_hat_img > 0] = [0, 0, 255]  # 将提取的白色区域标记为红色

    # 4. 显示结果
    plt.figure(figsize=(18, 6))

    plt.subplot(131)
    plt.imshow(binary_img, cmap='gray')
    plt.title("原始二值图像")
    plt.axis('off')

    plt.subplot(132)
    plt.imshow(top_hat_img, cmap='gray')
    plt.title(f"顶帽变换结果 (核大小: {KERNEL_SIZE})")
    plt.axis('off')

    plt.subplot(133)
    plt.imshow(highlighted_img)
    plt.title("在原图上高亮显示提取区域")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()
(五)通道与色彩空间处理类:优化色彩信息

不同色彩空间各有优势(如 RGB 适合显示,HSV 适合颜色分割),通道处理可聚焦特定色彩特征。

1. 白平衡

修正图像的色温偏差(如偏黄的室内照片),让白色物体在图像中呈现纯白(R=G=B)。

代码语言:javascript
复制
import cv2
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'ALi2.jpg'


# --- 主程序 ---
def gray_world_white_balance(image):
    """
    使用灰度世界算法进行白平衡校正。
    原理:假设一幅图像的R, G, B三个通道的平均强度应该相等(即为“灰度”)。
    通过调整每个通道的增益,使它们的平均值达到平衡。
    """
    # 计算每个通道的平均值
    b_avg = np.mean(image[:, :, 0])
    g_avg = np.mean(image[:, :, 1])
    r_avg = np.mean(image[:, :, 2])

    # 计算总平均值
    avg = (b_avg + g_avg + r_avg) / 3.0

    # 计算每个通道的增益
    b_gain = avg / b_avg
    g_gain = avg / g_avg
    r_gain = avg / r_avg

    # 应用增益进行校正
    balanced_image = image.copy()
    balanced_image[:, :, 0] = np.clip(image[:, :, 0] * b_gain, 0, 255)
    balanced_image[:, :, 1] = np.clip(image[:, :, 1] * g_gain, 0, 255)
    balanced_image[:, :, 2] = np.clip(image[:, :, 2] * r_gain, 0, 255)

    return balanced_image.astype(np.uint8)


def main():
    # 1. 读取图像 (OpenCV默认读取为BGR格式)
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return

    # 2. 执行白平衡校正
    # 使用我们定义的灰度世界算法
    balanced_img_bgr = gray_world_white_balance(img_bgr)

    # 3. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
    plt.title("原始图像 (可能存在色偏)")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(cv2.cvtColor(balanced_img_bgr, cv2.COLOR_BGR2RGB))
    plt.title("灰度世界算法白平衡校正后")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()

方法:通过灰色世界假设(图像平均为灰色)或白点检测调整三通道增益。

2. 色彩空间变换

支持 RGB↔HSV(HSV 的 H 通道直接对应颜色,适合按颜色分割)、RGB↔Lab(L 通道代表亮度,适合光照鲁棒性处理)等转换。

代码语言:javascript
复制
import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'XiaoYan.jpg'


# --- 主程序 ---
def main():
    # 1. 读取图像 (OpenCV默认读取为BGR格式)
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return

    # 2. 执行色彩空间转换
    # BGR -> RGB (用于Matplotlib正确显示)
    img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)

    # BGR -> HSV (常用于颜色过滤)
    img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)

    # BGR -> YCrCb (常用于肤色检测和视频压缩)
    img_ycrcb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2YCrCb)

    # 3. 显示结果
    plt.figure(figsize=(18, 6))

    plt.subplot(141)
    plt.imshow(img_rgb)
    plt.title("1. RGB 色彩空间")
    plt.axis('off')

    plt.subplot(142)
    plt.imshow(img_bgr)  # Matplotlib会将BGR当作RGB显示,颜色会失真,用于对比
    plt.title("2. BGR 色彩空间 (OpenCV)")
    plt.axis('off')

    plt.subplot(143)
    plt.imshow(img_hsv)  # HSV的可视化效果并不直观,但其通道有明确物理意义
    plt.title("3. HSV 色彩空间")
    plt.axis('off')

    plt.subplot(144)
    plt.imshow(img_ycrcb)  # YCrCb的可视化效果也不直观
    plt.title("4. YCrCb 色彩空间")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()
3. 通道分离与合并

将多通道图像拆分为单通道(如 RGB 拆分为 R、G、B)单独处理(如仅增强 R 通道),再合并为多通道图像。

代码语言:javascript
复制
import cv2
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'PuTiGuShu.jpg'


# --- 主程序 ---
def main():
    # 1. 读取图像 (OpenCV默认读取为BGR格式)
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return

    # 2. 执行通道分离
    # split() 函数将BGR图像分离成三个单通道数组
    b_channel, g_channel, r_channel = cv2.split(img_bgr)

    # 创建一个与原图大小相同的黑色图像,用于后续合并演示
    zeros = np.zeros(img_bgr.shape[:2], dtype="uint8")

    # 3. 执行通道合并 (为了可视化每个通道)
    # 将每个通道与黑色图像合并,以显示单个通道的颜色
    merged_b = cv2.merge([b_channel, zeros, zeros])  # 只显示蓝色通道
    merged_g = cv2.merge([zeros, g_channel, zeros])  # 只显示绿色通道
    merged_r = cv2.merge([zeros, zeros, r_channel])  # 只显示红色通道

    # 原始的合并方式
    merged_original = cv2.merge([b_channel, g_channel, r_channel])

    # 4. 显示结果
    plt.figure(figsize=(18, 10))

    plt.subplot(231)
    plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
    plt.title("原始RGB图像")
    plt.axis('off')

    plt.subplot(232)
    plt.imshow(b_channel, cmap='gray')
    plt.title("B通道 (灰度)")
    plt.axis('off')

    plt.subplot(233)
    plt.imshow(merged_b)  # OpenCV显示,BGR格式
    plt.title("仅B通道 (彩色)")
    plt.axis('off')

    plt.subplot(234)
    plt.imshow(g_channel, cmap='gray')
    plt.title("G通道 (灰度)")
    plt.axis('off')

    plt.subplot(235)
    plt.imshow(merged_g)  # OpenCV显示,BGR格式
    plt.title("仅G通道 (彩色)")
    plt.axis('off')

    plt.subplot(236)
    plt.imshow(r_channel, cmap='gray')
    plt.title("R通道 (灰度)")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()
(六)数据增强类:提升模型泛化能力

在深度学习中,数据增强通过随机变换原始图像生成新样本,解决数据集不足导致的过拟合问题。

1. 随机亮度 / 对比度调整

在一定范围内随机增减亮度(像素值整体偏移)或对比度(像素值分布拉伸),模拟不同光照条件。

代码语言:javascript
复制
import cv2
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'XiaoYan.jpg'
BRIGHTNESS_FACTOR = 0.2  # 亮度调整因子,例如±20%
CONTRAST_FACTOR = 0.2  # 对比度调整因子,例如±20%


# --- 主程序 ---
def adjust_brightness_contrast(image, brightness_factor, contrast_factor):
    """
    调整图像的亮度和对比度。
    new_pixel = alpha * old_pixel + beta
    alpha 控制对比度 (alpha > 1 增强, alpha < 1 减弱)
    beta 控制亮度 (beta > 0 变亮, beta < 0 变暗)
    """
    # 随机生成 alpha 和 beta
    alpha = np.random.uniform(1 - contrast_factor, 1 + contrast_factor)
    beta = np.random.uniform(-brightness_factor * 255, brightness_factor * 255)

    # 执行调整
    adjusted = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)
    return adjusted, alpha, beta


def main():
    # 1. 读取图像
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return

    # 2. 执行随机亮度/对比度调整
    augmented_img, alpha, beta = adjust_brightness_contrast(img_bgr, BRIGHTNESS_FACTOR, CONTRAST_FACTOR)

    # 3. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
    plt.title("原始图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(cv2.cvtColor(augmented_img, cv2.COLOR_BGR2RGB))
    plt.title(f"增强后 (对比度 α={alpha:.2f}, 亮度 β={beta:.2f})")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()
2. 随机旋转 / 翻转 / 裁剪

随机旋转(如 - 15°~15°)、水平 / 垂直翻转、随机裁剪(如从中心区域随机裁剪 80% 区域),增加样本角度、方向多样性。

代码语言:javascript
复制
import cv2
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'ALi2.jpg'
ANGLE_RANGE = 30  # 随机旋转的角度范围,例如±30度


# --- 主程序 ---
def main():
    # 1. 读取图像
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return
    height, width = img_bgr.shape[:2]

    # 2. 执行随机旋转
    # 生成一个在 [-ANGLE_RANGE, ANGLE_RANGE] 范围内的随机角度
    angle = np.random.uniform(-ANGLE_RANGE, ANGLE_RANGE)

    # 获取旋转矩阵
    center = (width // 2, height // 2)
    rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0)

    # 执行旋转,使用黑色填充空白区域
    # 为了防止图像旋转后被裁剪,需要计算新的图像边界
    cos = np.abs(rotation_matrix[0, 0])
    sin = np.abs(rotation_matrix[0, 1])
    new_width = int((height * sin) + (width * cos))
    new_height = int((height * cos) + (width * sin))

    # 调整旋转矩阵以防止图像移位
    rotation_matrix[0, 2] += (new_width / 2) - center[0]
    rotation_matrix[1, 2] += (new_height / 2) - center[1]

    augmented_img = cv2.warpAffine(img_bgr, rotation_matrix, (new_width, new_height))

    # 3. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
    plt.title("原始图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(cv2.cvtColor(augmented_img, cv2.COLOR_BGR2RGB))
    plt.title(f"增强后 (随机旋转 {angle:.2f} 度)")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()
代码语言:javascript
复制
import cv2
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'XiaoYan.jpg'


# --- 主程序 ---
def main():
    # 1. 读取图像
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return

    # 2. 执行随机翻转
    # 生成一个0到1之间的随机数
    if np.random.rand() > 0.5:
        # 随机数大于0.5,则进行水平翻转
        augmented_img = cv2.flip(img_bgr, 1)  # 1 表示水平翻转
        flip_type = "水平翻转"
    else:
        # 随机数小于等于0.5,则进行垂直翻转
        augmented_img = cv2.flip(img_bgr, 0)  # 0 表示垂直翻转
        flip_type = "垂直翻转"

    # 3. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
    plt.title("原始图像")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(cv2.cvtColor(augmented_img, cv2.COLOR_BGR2RGB))
    plt.title(f"增强后 ({flip_type})")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()
代码语言:javascript
复制
import cv2
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME = 'XiaoYan.jpg'
CROP_SIZE_RATIO = 0.3  # 裁剪区域占原图像的比例,例如30%


# --- 主程序 ---
def main():
    # 1. 读取图像
    img_bgr = cv2.imread(IMAGE_FILENAME)
    if img_bgr is None:
        print(f"错误:找不到图像 '{IMAGE_FILENAME}'。")
        return
    height, width = img_bgr.shape[:2]

    # 2. 执行随机裁剪
    # 计算裁剪区域的大小
    crop_height = int(height * CROP_SIZE_RATIO)
    crop_width = int(width * CROP_SIZE_RATIO)

    # 随机生成裁剪区域的左上角坐标
    # 确保裁剪区域不会超出图像边界
    x = np.random.randint(0, width - crop_width + 1)
    y = np.random.randint(0, height - crop_height + 1)

    # 执行裁剪
    augmented_img = img_bgr[y:y + crop_height, x:x + crop_width]

    # 3. 显示结果
    plt.figure(figsize=(12, 6))

    plt.subplot(121)
    plt.imshow(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB))
    # 在原图上用红色方框标记出裁剪区域
    rect = plt.Rectangle((x, y), crop_width, crop_height, fill=False, edgecolor='red', linewidth=2)
    plt.gca().add_patch(rect)
    plt.title("原始图像 (红框为裁剪区域)")
    plt.axis('off')

    plt.subplot(122)
    plt.imshow(cv2.cvtColor(augmented_img, cv2.COLOR_BGR2RGB))
    plt.title("增强后 (随机裁剪)")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()
3. Mixup 混合增强

将两张图像按比例(如 α=0.3)混合(像素值:img = α*img1 + (1-α)*img2),标签也按同比例混合,提升模型对样本变化的适应力。

代码语言:javascript
复制
import cv2
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']

# --- 配置 ---
IMAGE_FILENAME_1 = 'ALi.jpg'
IMAGE_FILENAME_2 = 'XiaoYan.jpg'  # 需要另一张图像来进行混合


# --- 主程序 ---
def mixup_images(image1, image2, alpha=0.2):
    """
    实现MixUp数据增强。
    """
    # 确保两张图像大小相同
    if image1.shape != image2.shape:
        # 如果大小不同,将第二张图像 resize 到第一张的尺寸
        image2 = cv2.resize(image2, (image1.shape[1], image1.shape[0]))

    # 生成一个服从Beta分布的随机数 lambda
    lam = np.random.beta(alpha, alpha)

    # 按比例混合图像
    mixed_image = (lam * image1 + (1 - lam) * image2).astype(np.uint8)

    return mixed_image, lam


def main():
    # 1. 读取两张图像
    img1_bgr = cv2.imread(IMAGE_FILENAME_1)
    img2_bgr = cv2.imread(IMAGE_FILENAME_2)

    if img1_bgr is None or img2_bgr is None:
        print("错误:找不到其中一张或两张图像,请检查文件名和路径。")
        return

    # 2. 执行MixUp混合增强
    mixed_img, lam = mixup_images(img1_bgr, img2_bgr)

    # 3. 显示结果
    plt.figure(figsize=(18, 6))

    plt.subplot(131)
    plt.imshow(cv2.cvtColor(img1_bgr, cv2.COLOR_BGR2RGB))
    plt.title("图像 1")
    plt.axis('off')

    plt.subplot(132)
    plt.imshow(cv2.cvtColor(img2_bgr, cv2.COLOR_BGR2RGB))
    plt.title("图像 2")
    plt.axis('off')

    plt.subplot(133)
    plt.imshow(cv2.cvtColor(mixed_img, cv2.COLOR_BGR2RGB))
    plt.title(f"MixUp 混合后 (λ={lam:.2f})")
    plt.axis('off')

    plt.tight_layout()
    plt.show()  # 显示结果


if __name__ == '__main__':
    main()

四、实践组合建议

实际任务中需根据场景组合预处理操作,举例如下:

  • 文档识别流程:几何校正(修正倾斜)→ 灰度化 → 二值化(突出文字)→ 开运算(去噪点);
  • 图像分类训练:高斯滤波(去噪)→ 随机裁剪 / 翻转(数据增强)→ 归一化(适配模型输入);
  • 目标检测预处理:裁剪(ROI 提取)→ 对比度增强(突出目标)→ 色彩空间转换(HSV 分割)。

五、总结

图像预处理没有 “万能公式”,核心是理解每个操作的原理与适用场景。本文整理的六大类操作覆盖了从基础优化到数据增强的全流程。实际使用时需注意:

  1. 优先解决关键问题(如噪声严重先去噪,而非急于增强对比度);
  2. 平衡处理效果与效率(如实时场景选均值滤波,而非耗时的双边滤波)。

如果在集成过程中遇到问题,或有更优实现思路,欢迎在评论区交流~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-10-24,如有侵权请联系 [email protected] 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 [email protected] 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、图像预处理核心模块思维导图
  • 二、图像预处理一般流程
  • 三、核心操作详解
    • (一)像素值调整类:优化图像基础属性
      • 1. 二值化
      • 2. 灰度化
      • 3. 归一化
      • 4. 对比度增强
    • (二)几何变换类:调整图像空间形态
      • 1. 调整大小
      • 2. 翻转
      • 3. 旋转
      • 4. 裁剪
      • 5. 几何校正
    • (三)噪声处理类:提升图像纯净度
      • 1. 高斯滤波去噪
      • 2. 均值滤波去噪
      • 3. 去模糊
      • 4. 双边滤波
    • (四)形态学操作类:基于形状的特征优化
      • 1. 腐蚀
      • 2. 膨胀
      • 3. 开运算(先腐蚀后膨胀)
      • 4. 闭运算(先膨胀后腐蚀)
      • 5. 形态学梯度(膨胀 - 腐蚀)
      • 6. 顶帽变换(原始图像 - 开运算结果)
    • (五)通道与色彩空间处理类:优化色彩信息
      • 1. 白平衡
      • 2. 色彩空间变换
      • 3. 通道分离与合并
    • (六)数据增强类:提升模型泛化能力
      • 1. 随机亮度 / 对比度调整
      • 2. 随机旋转 / 翻转 / 裁剪
      • 3. Mixup 混合增强
  • 四、实践组合建议
  • 五、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档