3、OpenCV基础操作(一):图像的读取、显示、保存与属性
好,咱们正式开始动手写代码了。这一章的内容,说白了就是OpenCV的"Hello World"——图像的读取、显示、保存,外加几个最常用的属性查看。别小看这几步,我见过不少新手在这上面翻车,尤其是路径和颜色通道的问题。
我个人习惯,每开始一个新项目,第一件事就是先跑通图像的读写流程。这就像盖房子先打地基,地基稳了,后面做检测、训练模型才踏实。
本章核心知识点速览
- 读取图像:cv2.imread() 的三种模式
- 显示图像:cv2.imshow() + 窗口管理
- 保存图像:cv2.imwrite() 的格式与质量
- 图像属性:shape、dtype、size 的含义与用途
3.1 读取图像:cv2.imread()
读取图像是第一步。OpenCV 用 cv2.imread() 这个函数,传入文件路径就行。但这里有个坑——颜色通道顺序是 BGR,不是 RGB。我第一次用 OpenCV 显示图片时,发现颜色偏蓝,查了半天才发现是通道顺序搞反了。
import cv2
# 彩色模式读取(默认)
img_color = cv2.imread('cat.jpg', cv2.IMREAD_COLOR)
# 灰度模式读取
img_gray = cv2.imread('cat.jpg', cv2.IMREAD_GRAYSCALE)
# 原样读取(包含alpha通道等)
img_unchanged = cv2.imread('cat.jpg', cv2.IMREAD_UNCHANGED)
| 标志 | 数值 | 说明 |
|---|---|---|
cv2.IMREAD_COLOR |
1 | 默认值,加载彩色图像,忽略透明度 |
cv2.IMREAD_GRAYSCALE |
0 | 以灰度模式加载,单通道 |
cv2.IMREAD_UNCHANGED |
-1 | 包含alpha通道,原样加载 |
路径问题要小心
我曾经因为路径里带了中文,结果图像读不出来,排查了半天。OpenCV 的 imread 不支持中文路径,建议全部用英文路径。如果图像读出来是 None,先检查路径对不对。
3.2 显示图像:cv2.imshow()
读进来之后,总得看一眼吧?cv2.imshow() 负责把图像显示在窗口中。配合 cv2.waitKey() 和 cv2.destroyAllWindows() 一起用,才能正常关闭窗口。
cv2.imshow('My Image', img_color) # 第一个参数是窗口名
cv2.waitKey(0) # 等待按键,0表示无限等待
cv2.destroyAllWindows() # 关闭所有窗口
你想想看,如果不加 waitKey(),窗口会一闪而过,根本看不到。我个人习惯用 waitKey(0),按任意键再关闭,调试时很方便。
小技巧
如果想按特定键退出,可以判断返回值:
if cv2.waitKey(0) == ord('q'):
cv2.destroyAllWindows()
这样按 'q' 键才会关闭窗口,其他键没反应。
3.3 保存图像:cv2.imwrite()
处理完图像,得保存下来。cv2.imwrite() 根据文件扩展名自动选择保存格式。支持 .jpg、.png、.bmp 等常见格式。
# 保存为PNG
cv2.imwrite('output.png', img_color)
# 保存为JPEG,指定质量(0-100)
cv2.imwrite('output.jpg', img_color, [cv2.IMWRITE_JPEG_QUALITY, 95])
# 保存为PNG,指定压缩级别(0-9)
cv2.imwrite('output.png', img_color, [cv2.IMWRITE_PNG_COMPRESSION, 3])
| 格式 | 参数 | 说明 |
|---|---|---|
| JPEG | cv2.IMWRITE_JPEG_QUALITY |
质量值 0-100,默认 95,值越高文件越大 |
| PNG | cv2.IMWRITE_PNG_COMPRESSION |
压缩级别 0-9,默认 3,值越高文件越小 |
| WebP | cv2.IMWRITE_WEBP_QUALITY |
质量值 0-100,适合网络传输 |
保存路径同样不支持中文
和读取一样,保存路径也最好用英文。如果保存失败,返回 False,记得检查返回值。
3.4 图像属性:shape、dtype、size
图像读进来之后,我们得知道它长什么样。三个最常用的属性:shape、dtype、size。
print('图像形状:', img_color.shape) # (高度, 宽度, 通道数)
print('数据类型:', img_color.dtype) # uint8
print('像素总数:', img_color.size) # 高 * 宽 * 通道数
举个例子,一张 640x480 的彩色图像:
shape返回(480, 640, 3)—— 注意顺序是 高、宽、通道dtype返回uint8—— 每个像素值范围 0-255size返回921600—— 480 * 640 * 3
为什么 shape 是 (高, 宽, 通道)?
OpenCV 用 NumPy 数组存储图像,而 NumPy 数组的第一个维度是行(高度),第二个维度是列(宽度)。所以 shape 的顺序是 (height, width, channels)。刚开始容易搞反,我建议你每次读图后都打印一下 shape 确认。
3.5 完整示例:读取→显示→查看属性→保存
把上面所有操作串起来,写一个完整的流程:
import cv2
# 1. 读取图像
img = cv2.imread('cat.jpg')
if img is None:
print('图像读取失败,请检查路径')
exit()
# 2. 查看属性
print('shape:', img.shape)
print('dtype:', img.dtype)
print('size:', img.size)
# 3. 显示图像
cv2.imshow('Cat Image', img)
cv2.waitKey(0)
# 4. 保存灰度版本
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imwrite('cat_gray.jpg', img_gray)
cv2.destroyAllWindows()
嗯,这里要注意:cv2.cvtColor() 是颜色空间转换函数,后面章节会详细讲。这里只是演示一下保存处理后的结果。
调试小习惯
我每次写图像处理代码,都会先打印 shape 和 dtype,确认数据没问题再往下走。这能省掉很多莫名其妙的 bug。
3.6 常见问题与避坑
- 图像读出来是 None:路径不对、文件名有中文、文件损坏。先检查文件是否存在。
- 颜色不对:OpenCV 是 BGR 顺序,用 matplotlib 显示时记得转换:
cv2.cvtColor(img, cv2.COLOR_BGR2RGB)。 - 窗口卡死:忘了加
waitKey()或者destroyAllWindows()。 - 保存失败:路径无写入权限、磁盘空间不足、扩展名不支持。
好了,这一章的内容就这些。图像读取、显示、保存、属性查看,这四个操作是后续所有图像处理的基础。你可以在自己的电脑上找一张图片,把上面的代码跑一遍,感受一下 OpenCV 的工作方式。