3. OpenCV基础(一)
好,咱们正式开始接触OpenCV。这一章是基本功,说白了就是学会怎么把一张图片“请”进程序里,怎么在屏幕上看一眼,再决定要不要存下来。另外,色彩空间转换这块,在门禁系统里特别常用——你想想看,摄像头拍到的原始画面是BGR格式,但很多算法(比如人脸检测)要的是灰度图或者RGB,不转的话就会出问题。
3.1 图像的读取:imread() 的用法与坑
OpenCV读取图像用的是 cv2.imread()。这个函数很简单,但有几个细节我建议你记牢。
import cv2
# 读取彩色图像(默认方式)
img = cv2.imread('face.jpg')
print(type(img)) # <class 'numpy.ndarray'>
print(img.shape) # (高度, 宽度, 通道数)
嗯,这里要注意:imread() 默认返回的是 BGR 顺序的三通道数组,不是RGB。我在项目里第一次用的时候,直接拿它去显示,结果人脸颜色偏蓝,排查了半天才发现是通道顺序搞反了。
imread() 的第二个参数可以控制读取模式:
| 参数值 | 含义 | 实际用途 |
|---|---|---|
cv2.IMREAD_COLOR (1) |
彩色模式,默认 | 普通场景 |
cv2.IMREAD_GRAYSCALE (0) |
灰度模式 | 人脸检测前常用 |
cv2.IMREAD_UNCHANGED (-1) |
保留Alpha通道 | 处理PNG透明图 |
cv2.imdecode() 配合 np.fromfile() 处理。
3.2 图像的显示:imshow() 与窗口管理
读进来之后,总得看一眼吧?用 cv2.imshow()。
cv2.imshow('My Window', img)
cv2.waitKey(0) # 等待按键,0表示无限等待
cv2.destroyAllWindows()
这里有个关键点:imshow() 之后必须跟 waitKey(),否则窗口一闪就没了。我个人习惯把 waitKey(0) 写成 cv2.waitKey(0) & 0xFF,这样在64位系统上更安全。
cv2.namedWindow('win', cv2.WINDOW_NORMAL) 创建窗口,然后再 imshow(),这样就能手动拖拽缩放。
3.3 图像的保存:imwrite() 的格式与质量
保存图像用 cv2.imwrite()。它根据文件后缀自动判断格式。
cv2.imwrite('output.jpg', img) # JPEG格式
cv2.imwrite('output.png', img) # PNG格式
cv2.imwrite('output.bmp', img) # BMP格式
对于JPEG,你可以控制压缩质量:
cv2.imwrite('output_high.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 95])
质量范围是0-100,默认95。数值越大,文件越大,画质越好。我在做门禁系统时,保存抓拍的人脸图片一般用90,既能看清人脸,又不会太占硬盘。
imwrite() 保存的是BGR顺序的数据。如果你之前把图像转成了RGB,直接保存会颜色错乱。一定要先转回BGR再保存。
3.4 色彩空间转换:BGR ↔ RGB ↔ 灰度
这是本章的重头戏。OpenCV使用 cv2.cvtColor() 进行转换。
3.4.1 BGR 转 RGB
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
为什么要转?因为Matplotlib显示图像时默认用RGB顺序。如果你用 plt.imshow() 直接显示OpenCV读进来的图,颜色会完全不对。我刚开始学的时候就被这个坑过,显示出来的人脸像阿凡达。
3.4.2 BGR 转灰度图
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
print(img_gray.shape) # (高度, 宽度) —— 只有两个维度
灰度图只有一个通道,每个像素值0-255。0是纯黑,255是纯白。门禁系统中的人脸检测算法(比如Haar Cascade)通常要求输入灰度图,因为灰度图计算量小,而且光照变化的影响相对可控。
cv2.imread() 直接加参数0也能读成灰度图,但如果你后续需要彩色信息(比如肤色检测),就别用这个方式。我建议统一读成彩色,再根据需要转换。
3.4.3 其他常用转换
| 转换代码 | 用途 |
|---|---|
COLOR_BGR2HSV |
色调、饱和度、明度,适合颜色分割 |
COLOR_BGR2LAB |
亮度、绿红、蓝黄,适合颜色分析 |
COLOR_GRAY2BGR |
灰度转三通道(伪彩色) |
3.5 本章知识体系
下面这张图帮你理清本章的核心流程:
3.6 完整示例:读取→转灰度→显示→保存
把今天学的串起来,写一个完整的脚本:
import cv2
# 1. 读取彩色图像
img_bgr = cv2.imread('face.jpg')
if img_bgr is None:
print("图片读取失败,检查路径")
exit()
# 2. 转灰度图
img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
# 3. 显示原图和灰度图
cv2.imshow('Original BGR', img_bgr)
cv2.imshow('Gray', img_gray)
# 4. 保存灰度图
cv2.imwrite('face_gray.jpg', img_gray)
# 5. 等待按键退出
cv2.waitKey(0)
cv2.destroyAllWindows()
imshow() 但不加 waitKey(1),结果窗口卡死。记住,waitKey() 不只是等待按键,它还负责刷新窗口事件。没有它,窗口不会更新。
好了,这一章的内容就这些。图像读取、显示、保存是OpenCV的“三板斧”,色彩空间转换是后续所有图像处理的基础。你把这些练熟了,后面做人脸检测、特征提取就会顺手很多。