图像预处理-最全总结

2026-02-10 03:37:10

在计算机视觉领域,图像预处理是连接原始图像与高阶任务(如目标检测、图像分类、语义分割)的关键桥梁。原始图像往往存在噪声、光照不均、尺寸不一等问题,直接影响后续算法的效果。本文系统整理了六大类核心预处理操作,涵盖像素调整、几何变换、噪声处理等,所有操作均提供可直接复用的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 分割)。五、总结 图像预处理没有 “万能公式”,核心是理解每个操作的原理与适用场景。本文整理的六大类操作覆盖了从基础优化到数据增强的全流程。实际使用时需注意:

优先解决关键问题(如噪声严重先去噪,而非急于增强对比度);平衡处理效果与效率(如实时场景选均值滤波,而非耗时的双边滤波)。如果在集成过程中遇到问题,或有更优实现思路,欢迎在评论区交流~

Posted in 活动档案
Copyright © 2088 热剧网游活动档案馆 All Rights Reserved.
友情链接