2、OpenCV基础回顾:图像读取、显示、保存,色彩空间转换(BGR、RGB、GRAY)

好,咱们正式开始动手。这一章我带你快速过一遍 OpenCV 最核心的基础操作。别小看这些,我见过不少项目后期出 bug,追根溯源都是最开始的读写和颜色空间搞错了。

2.1 图像读取:imread 的隐藏细节

OpenCV 读取图像用 cv2.imread()。语法很简单,但有几个参数你得上心。

import cv2

# 默认以彩色模式读取 (BGR)
img = cv2.imread('cat.jpg')

# 以灰度模式读取
img_gray = cv2.imread('cat.jpg', cv2.IMREAD_GRAYSCALE)

# 读取包含透明通道的图像
img_unchanged = cv2.imread('cat.png', cv2.IMREAD_UNCHANGED)
我曾经踩过的坑:路径别带中文!OpenCV 的 imread 对中文路径支持很差,返回 None 还不报错。你排查半天,结果只是文件夹名字有个“测试”。我现在的习惯是:所有图像路径统一用英文,或者用 os.path.join() 拼接。

另外,imread 返回 None 时不会抛异常。所以读取后一定要加个判断:

if img is None:
    print("图像加载失败,检查路径")
    exit()
标志 值 说明
cv2.IMREAD_COLOR 1 默认,加载为 BGR 三通道,忽略透明通道
cv2.IMREAD_GRAYSCALE 0 加载为单通道灰度图
cv2.IMREAD_UNCHANGED -1 保留所有通道,包括 alpha

2.2 图像显示与保存

显示图像用 cv2.imshow(),配合 cv2.waitKey() 和 cv2.destroyAllWindows() 才能正常关闭窗口。

cv2.imshow('My Image', img)
cv2.waitKey(0)      # 等待任意按键
cv2.destroyAllWindows()
我个人的习惯:调试时我会把 waitKey(0) 改成 waitKey(1) 配合循环,这样能实时看到处理效果。但正式演示时还是用 0,免得画面一闪而过。

保存图像用 cv2.imwrite()。注意,保存的质量和格式有关:

# 保存为 PNG(无损)
cv2.imwrite('output.png', img)

# 保存为 JPEG,指定质量 95(0-100)
cv2.imwrite('output.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 95])
注意:imwrite 保存的是 BGR 顺序。如果你用 matplotlib 的 plt.imshow() 显示,颜色会偏蓝偏黄。为什么?因为 matplotlib 默认用 RGB。这个问题我当年调了半小时才反应过来。

2.3 色彩空间转换:BGR、RGB、GRAY

这是本章的重头戏。OpenCV 默认用 BGR 顺序,而大多数图像处理库(如 matplotlib、PIL)用 RGB。你想想看,如果不转换,显示出来的图像颜色完全不对。

转换函数是 cv2.cvtColor():

# BGR 转 RGB
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# BGR 转灰度
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# RGB 转 BGR(反向转换)
img_bgr = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR)
核心要点:YOLO 推理时,模型通常要求输入 RGB 图像。但 OpenCV 读取的是 BGR。所以你在送入模型前,必须做一次 BGR→RGB 转换。我见过有人忘了这步,模型精度直接掉一半。

灰度转换的原理是加权平均:Gray = 0.299*R + 0.587*G + 0.114*B。OpenCV 内部已经优化好了,直接用就行。

转换代码 用途
cv2.COLOR_BGR2RGB BGR → RGB,用于正确显示或送入深度学习模型
cv2.COLOR_BGR2GRAY BGR → 灰度,用于边缘检测、特征提取等
cv2.COLOR_GRAY2BGR 灰度 → BGR,将单通道复制为三通道
cv2.COLOR_BGR2HSV BGR → HSV,用于颜色分割、目标跟踪

2.4 实战:图像读取与色彩空间转换流程

下面我把整个流程串起来,写一个完整的示例。这也是我平时调试图像处理管线的标准模板。

import cv2
import numpy as np

# 1. 读取图像
img_bgr = cv2.imread('test.jpg')
if img_bgr is None:
    print("图像读取失败")
    exit()

# 2. 显示原始 BGR 图像
cv2.imshow('Original BGR', img_bgr)

# 3. 转换为 RGB
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)

# 4. 转换为灰度
img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

# 5. 显示结果
cv2.imshow('RGB', img_rgb)
cv2.imshow('Gray', img_gray)

# 6. 保存灰度图
cv2.imwrite('gray_output.jpg', img_gray)

cv2.waitKey(0)
cv2.destroyAllWindows()
避坑指南:如果你用 Jupyter Notebook,cv2.imshow() 可能会崩溃。我建议用 matplotlib 的 imshow() 来显示,但记得先转成 RGB。或者直接用 cv2_imshow()(Google Colab 专用)。

2.5 知识体系:图像基础操作流程

下面这张图概括了本章的核心逻辑。你看一遍就能记住整个流程。

图像基础操作流程 cv2.imread() 检查 img is None? 打印错误并退出 图像加载成功 cvtColor 转换 BGR → RGB BGR → GRAY BGR → HSV 注意:OpenCV 默认 BGR,送入 YOLO 前必须转为 RGB

2.6 本章小结

  • imread:默认 BGR,路径别带中文,记得判空。
  • imshow + waitKey:成对出现,否则窗口卡死。
  • imwrite:保存的是 BGR 顺序,用 matplotlib 显示前要转 RGB。
  • cvtColor:BGR→RGB 是 YOLO 推理前的必备步骤。

说白了,这一章就是给后面所有章节打地基。你把这些基础操作练熟了,后面做帧处理、做推理加速才不会手忙脚乱。我当年刚学 OpenCV 时,光 BGR 和 RGB 的坑就踩了不下十次。你现在记住,后面就省心了。