第二章 OpenCV基础(一):图像读取与显示、图像属性、色彩空间转换、图像保存

好,咱们正式开始动手了。

OpenCV 就像一把瑞士军刀,功能很全。但再厉害的刀,也得先学会怎么拿、怎么看、怎么放回去。这一章,我们就搞定图像最基本的四个操作:读、看、改、存。

别小看这些基础。我见过不少新手,上来就调模型,结果图像路径写错了、色彩空间搞混了,折腾半天。基础打牢,后面才稳。

2.1 图像读取:imread() 的玄机

读取图像,用的是 cv2.imread()。语法很简单:

import cv2

# 读取图像
img = cv2.imread('cat.jpg')

嗯,这里要注意。OpenCV 默认读取的是 BGR 格式,不是我们常见的 RGB。这一点特别容易踩坑。

⚠️ 我曾经犯过的错: 刚用 OpenCV 时,我用 matplotlib 显示图像,结果颜色全偏蓝。查了半天才发现,matplotlib 默认是 RGB,而 OpenCV 读进来是 BGR。所以显示前必须转换。

imread() 还有第二个参数,控制读取方式:

参数值 含义 常用场景
cv2.IMREAD_COLOR (1) 彩色图像,忽略透明度 默认值,日常使用
cv2.IMREAD_GRAYSCALE (0) 灰度图像 减少计算量,很多检测算法输入
cv2.IMREAD_UNCHANGED (-1) 包含 Alpha 通道 处理 PNG 透明图

我个人习惯,做 YOLO 检测时,如果不需要颜色信息,直接读成灰度图。速度能快不少。

2.2 图像显示:imshow() 与窗口管理

读进来,总得看一眼吧?用 cv2.imshow()。

cv2.imshow('窗口标题', img)
cv2.waitKey(0)  # 等待按键
cv2.destroyAllWindows()

这里有个关键点:waitKey() 不能省。它有两个作用:

  • 保持窗口显示,直到你按键盘
  • 返回按键的 ASCII 码,可以用来做交互
💡 小技巧: 如果你想让窗口自动关闭,可以写 cv2.waitKey(3000),表示等待 3 秒后自动关闭。我调试时经常用这个,省得一直按键盘。

另外,destroyAllWindows() 是关闭所有窗口。如果你只关一个,用 cv2.destroyWindow('窗口标题')。

2.3 图像属性:shape、dtype、size

图像在 OpenCV 里其实就是一个 NumPy 数组。所以它的属性,就是数组的属性。

print(img.shape)   # (高度, 宽度, 通道数)
print(img.dtype)   # uint8
print(img.size)    # 总像素数 = 高 × 宽 × 通道数

举个例子:一张 640×480 的彩色图,shape 返回 (480, 640, 3)。size 就是 480×640×3 = 921600。

为什么是 uint8?因为每个像素值范围是 0-255,刚好 8 位无符号整数。这个后面做图像处理时很重要——你如果做加减法,一不小心就会溢出。

📌 重点记忆: OpenCV 中图像坐标是 (行, 列),也就是 (y, x)。这和很多人的直觉相反。我刚开始写代码时,经常把 x 和 y 搞反,画框画到天上去。

2.4 色彩空间转换:BGR ↔ RGB ↔ 灰度

这是本章的重头戏。色彩空间转换用 cv2.cvtColor()。

2.4.1 BGR 转 RGB

img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

为什么转?因为 matplotlib、PIL 这些库用的是 RGB。你不转,显示出来就是蓝汪汪一片。

2.4.2 BGR 转灰度

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

灰度图只有一个通道,shape 变成 (高, 宽)。YOLO 检测时,很多轻量模型输入就是灰度图,能省三分之一的计算量。

2.4.3 其他常见转换

转换代码 说明 应用场景
COLOR_BGR2HSV BGR → HSV 颜色分割、物体跟踪
COLOR_BGR2LAB BGR → Lab 颜色距离计算
COLOR_BGR2YUV BGR → YUV 视频编码、YOLO 输入

我个人在项目中用得最多的是 BGR2RGB 和 BGR2GRAY。HSV 在做颜色过滤时很管用,比如提取红色区域。

⚠️ 避坑指南: 我曾经在循环里反复调用 cvtColor,结果帧率掉到 10 帧以下。后来发现,每帧只转一次,而且尽量用灰度图,性能提升很明显。

2.5 图像保存:imwrite()

处理完了,得存下来。用 cv2.imwrite()。

cv2.imwrite('output.jpg', img)

它支持多种格式:jpg、png、bmp、tiff 等。保存时还可以指定参数:

# 保存为高质量 JPEG
cv2.imwrite('output.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 95])

# 保存为 PNG 压缩级别
cv2.imwrite('output.png', img, [cv2.IMWRITE_PNG_COMPRESSION, 3])

JPEG 质量范围是 0-100,默认 95。PNG 压缩级别是 0-9,0 表示不压缩,9 表示最大压缩。我一般用 3,平衡速度和大小。

💡 经验之谈: 如果你要保存处理后的图像用于训练,建议用 PNG 格式。JPEG 是有损压缩,会引入噪点,影响模型训练效果。

2.6 本章知识结构图

下面这张图,把本章的核心流程串起来了:

OpenCV 图像基础操作流程 OpenCV 图像基础操作流程 图像读取 imread() 图像属性 shape/dtype/size 色彩空间转换 cvtColor() 图像显示 imshow() 图像保存 imwrite() 💡 核心流程:读取 → 查看属性 → 转换色彩空间 → 显示或保存 注意:imread() 默认 BGR 格式,显示前需转 RGB;灰度图可提升性能

2.7 完整示例:一条龙操作

把上面所有知识点串起来,写一个完整的例子:

import cv2

# 1. 读取图像
img = cv2.imread('cat.jpg', cv2.IMREAD_COLOR)

# 2. 查看属性
print(f"图像尺寸: {img.shape}")
print(f"数据类型: {img.dtype}")
print(f"总像素数: {img.size}")

# 3. 转灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 4. 显示原图和灰度图
cv2.imshow('Original', img)
cv2.imshow('Gray', gray)

# 5. 等待按键后保存
key = cv2.waitKey(0)
if key == ord('s'):  # 按 s 键保存
    cv2.imwrite('gray_cat.jpg', gray)
    print("保存成功!")
else:
    print("未保存")

cv2.destroyAllWindows()

这个例子,你跑一遍,基本就掌握了本章所有内容。我建议你换几张自己的图片试试,感受一下不同格式、不同尺寸的差异。

📌 本章核心要点:
  • imread() 默认 BGR,不是 RGB
  • 图像本质是 NumPy 数组,shape 是 (高, 宽, 通道)
  • cvtColor() 是色彩空间转换的唯一入口
  • imwrite() 保存时注意格式和质量参数
  • 灰度图能显著提升处理速度