2. 图像基础操作:读取、显示、保存与颜色空间转换
好,咱们正式开始动手了。
这一章,我带你搞定图像处理里最基础、也最常用的几个操作。说白了,就是怎么把一张图片弄进程序里,怎么看看它长什么样,处理完了怎么存回去,以及最核心的——颜色空间到底是个啥玩意儿。
你别小看这些基础操作。我见过不少新手,上来就搞高大上的检测算法,结果连图片路径写错了都不知道,程序报错一脸懵。嗯,咱们先把地基打牢。
2.1 图像的读取:imread() 的玄机
在 OpenCV 里,读取图像用的是 cv2.imread()。这个函数很简单,但有几个坑,我当年刚入行时就踩过。
import cv2
# 读取彩色图像
img = cv2.imread('lena.jpg')
print(type(img)) # <class 'numpy.ndarray'>
print(img.shape) # (高度, 宽度, 通道数)
你看,读进来的图像其实就是一个 NumPy 数组。形状是 (高度, 宽度, 通道数)。
imread() 的第二个参数可以控制读取方式:
| 参数 | 含义 | 数值 |
|---|---|---|
cv2.IMREAD_COLOR |
读取彩色图像(默认) | 1 |
cv2.IMREAD_GRAYSCALE |
读取为灰度图 | 0 |
cv2.IMREAD_UNCHANGED |
保留原图所有通道(含 Alpha) | -1 |
# 读取灰度图
gray_img = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)
print(gray_img.shape) # (高度, 宽度) —— 只有两个维度
2.2 图像的显示:imshow() 与窗口管理
读进来了,总得看一眼吧?用 cv2.imshow()。
cv2.imshow('窗口标题', img)
cv2.waitKey(0) # 等待按键,参数是毫秒数,0 表示无限等待
cv2.destroyAllWindows() # 关闭所有窗口
这里有个关键点:waitKey() 必须要有。没有它,窗口一闪就没了,你根本看不到图像。
为什么会这样?因为 OpenCV 的显示机制是事件驱动的。你不调用 waitKey(),它就不处理窗口事件,直接往下执行程序,然后退出。
🔑 核心要点:
waitKey(0):等待任意按键,常用于单张图片显示waitKey(30):等待 30 毫秒,常用于视频流显示- 按 ESC 键(ASCII 码 27)通常用来退出
# 一个完整的显示示例
img = cv2.imread('lena.jpg')
cv2.imshow('My Image', img)
key = cv2.waitKey(0)
if key == 27: # ESC
cv2.destroyAllWindows()
elif key == ord('s'): # 按 s 键保存
cv2.imwrite('output.jpg', img)
cv2.destroyAllWindows()
嗯,这里我顺便把保存也讲了。你看,按 s 键就能保存图像,挺方便的吧?
2.3 图像的保存:imwrite() 的注意事项
cv2.imwrite() 用来保存图像。它根据文件扩展名自动选择编码格式。
cv2.imwrite('output.png', img) # 保存为 PNG
cv2.imwrite('output.jpg', img) # 保存为 JPEG
JPEG 的压缩质量可以通过 cv2.IMWRITE_JPEG_QUALITY 控制:
# 设置 JPEG 质量为 95(范围 0-100)
cv2.imwrite('output.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 95])
2.4 颜色空间转换:BGR 与灰度
终于到重点了。颜色空间转换,说白了就是把图像从一种颜色表示方式变成另一种。
最常用的就是 BGR 转灰度图。为什么需要灰度图?因为很多算法(比如边缘检测、特征提取)在单通道上计算更快,而且不受颜色干扰。
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
你想想看,一张彩色图有三个通道,灰度图只有一个通道。处理速度能快三倍,这可不是小数目。
反过来,灰度图也可以转回 BGR:
color = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)
但注意,这种转换只是把灰度值复制到三个通道上,并不是真的恢复了颜色信息。丢失的颜色是找不回来的。
🔑 常用转换标志:
cv2.COLOR_BGR2GRAY:BGR 转灰度cv2.COLOR_GRAY2BGR:灰度转 BGRcv2.COLOR_BGR2RGB:BGR 转 RGB(用于 matplotlib 显示)cv2.COLOR_BGR2HSV:BGR 转 HSV(颜色检测常用)
2.5 实战:一个完整的图像处理流程
来,咱们把今天学的串起来,写一个完整的例子。
import cv2
# 1. 读取图像
img = cv2.imread('lena.jpg')
if img is None:
print("图片没找到,检查路径!")
exit()
# 2. 显示原图
cv2.imshow('Original', img)
# 3. 转灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 4. 显示灰度图
cv2.imshow('Gray', gray)
# 5. 保存灰度图
cv2.imwrite('lena_gray.jpg', gray)
# 6. 等待按键
cv2.waitKey(0)
cv2.destroyAllWindows()
img is None。我在项目里吃过这个亏——路径写错了,程序没报错,但后面所有操作都崩溃,排查了半天才发现是图片没读进来。
2.6 本章小结
今天咱们干了这几件事:
- 用
imread()读取图像,注意 BGR 格式和路径问题 - 用
imshow()+waitKey()显示图像,别忘了等待按键 - 用
imwrite()保存图像,注意格式和质量 - 用
cvtColor()做颜色空间转换,BGR 和灰度是最常用的
这些操作看起来简单,但它们是所有图像处理任务的基石。你想想看,后面我们要做的运动检测、行为分析,哪一步离得开这些基础操作?
下一章,咱们聊聊图像的几何变换——缩放、旋转、裁剪。这些操作在预处理阶段特别重要,我到时候会分享一些实际项目中的小技巧。
好,今天就到这儿。动手试试吧,把代码敲一遍,感受一下。