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



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

将图像转换为仅含黑白两种颜色的二值图像(像素值 0 或 255),通过设定阈值区分前景(如文字、目标)和背景。
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()
应用场景:文字识别、条形码提取、轮廓分割(消除灰度渐变干扰)。
将 RGB 三通道彩色图像转换为单通道灰度图(像素值 0-255),通过加权平均三通道值实现(如:Gray=0.299R + 0.587G + 0.114*B)。
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 的数据量,同时保留图像轮廓特征,是多数算法(如边缘检测)的前置步骤。
将像素值映射到固定区间(如 [0,1] 或 [-1,1]),解决不同图像像素范围差异(如有的 0-255,有的 0-1023)。
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()
作用:避免因像素值范围不一致导致模型收敛困难(如神经网络输入需标准化)。
通过拉伸或压缩像素值分布范围(如直方图均衡化),扩大明暗区域差异。
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()
效果:让暗部细节变清晰(如逆光照片),亮部不过曝。
几何变换不改变像素颜色,仅调整像素的空间位置,解决图像尺寸不统一、角度偏差等问题。
按比例或固定尺寸缩放图像(如将 1024x768 缩放到 224x224 适配 CNN 输入),常用双线性插值(平衡速度与效果)。
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()
注意:等比例缩放避免目标变形(如人脸拉伸)。
包括水平翻转(左右镜像)和垂直翻转(上下颠倒),操作简单但能有效增加样本多样性。
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()
应用:数据增强(如训练集加入翻转图像,提升模型对方向的鲁棒性)。
围绕中心或指定点旋转任意角度(如 90°、45°),需处理旋转后空白区域(常用填充背景色或边缘像素)。
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()
场景:修正倾斜图像(如扫描文档的歪斜)。
从图像中提取感兴趣区域(ROI),如从身份证照片中裁剪出头像区域。
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()
优势:去除冗余信息,聚焦核心目标,减少算法计算量。
修正因拍摄角度导致的畸变(如透视畸变:矩形拍成长梯形),通过透视变换还原真实形状。
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()
典型案例:扫描文档校正、车牌倾斜修正。
原始图像易受传感器、环境干扰产生噪声(如低光拍摄的雪花噪点),噪声会掩盖细节,需针对性去除。
用高斯核(中间值大、边缘值小的矩阵)与图像卷积,平滑像素突变,适合去除高斯噪声(分布符合正态分布的噪声)。
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()
特点:平滑效果柔和,但可能模糊边缘。
用邻域像素的平均值替换当前像素,简单高效,适合去除椒盐噪声(随机出现的黑白点噪声)。
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()
注意:核越大去噪越强,但细节损失越多。【
针对运动模糊(如拍摄移动物体的拖影)或失焦模糊,通过逆滤波、维纳滤波等算法恢复清晰度。
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()
难点:需估计模糊核(如运动方向和距离)。
同时考虑空间距离(类似高斯滤波)和像素值差异(保留边缘:边缘处像素值差异大,不被平滑),实现 “去噪 + 保边” 双重效果。
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 矩形、十字形)为工具,通过腐蚀、膨胀等组合,提取图像形状特征。
用结构元素遍历图像,仅保留结构元素完全覆盖的前景像素,实现 “收缩前景、去除小噪点”。
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()
效果:细线条变细,小斑块消失。
与腐蚀相反,保留结构元素部分覆盖的前景像素,实现 “扩大前景、连接断裂区域”。
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()
效果:细线条变粗,缺口被填充。
先腐蚀去除小噪点,再膨胀恢复前景形状,适合 “去噪且不改变主体大小”(如去除细胞图像中的杂点)。
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()
先膨胀填充小孔洞,再腐蚀恢复前景形状,适合 “填洞且不改变主体大小”(如修复目标内部的空洞)。
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()
通过膨胀与腐蚀的差值,提取前景边缘轮廓,比传统边缘检测更清晰(抗噪性强)。
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()
突出比周围亮的小区域(如 X 光片中的亮斑),适合低对比度图像的细节提取。
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 适合颜色分割),通道处理可聚焦特定色彩特征。
修正图像的色温偏差(如偏黄的室内照片),让白色物体在图像中呈现纯白(R=G=B)。
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()
方法:通过灰色世界假设(图像平均为灰色)或白点检测调整三通道增益。
支持 RGB↔HSV(HSV 的 H 通道直接对应颜色,适合按颜色分割)、RGB↔Lab(L 通道代表亮度,适合光照鲁棒性处理)等转换。
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()
将多通道图像拆分为单通道(如 RGB 拆分为 R、G、B)单独处理(如仅增强 R 通道),再合并为多通道图像。
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()
在深度学习中,数据增强通过随机变换原始图像生成新样本,解决数据集不足导致的过拟合问题。
在一定范围内随机增减亮度(像素值整体偏移)或对比度(像素值分布拉伸),模拟不同光照条件。
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()
随机旋转(如 - 15°~15°)、水平 / 垂直翻转、随机裁剪(如从中心区域随机裁剪 80% 区域),增加样本角度、方向多样性。
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()
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()
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()
将两张图像按比例(如 α=0.3)混合(像素值:img = α*img1 + (1-α)*img2),标签也按同比例混合,提升模型对样本变化的适应力。
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()
实际任务中需根据场景组合预处理操作,举例如下:
图像预处理没有 “万能公式”,核心是理解每个操作的原理与适用场景。本文整理的六大类操作覆盖了从基础优化到数据增强的全流程。实际使用时需注意:
如果在集成过程中遇到问题,或有更优实现思路,欢迎在评论区交流~