2、OpenCV基础操作:图像读取与显示、图像属性获取、图像保存、视频读取与显示、摄像头初始化
好,咱们正式开始动手了。这一章我带你把OpenCV最基础的操作过一遍。说白了,就是学会怎么让电脑“看”到图像和视频。别小看这些操作,我做了这么多年视觉项目,每天跟它们打交道。你想想看,摄像头都打不开,后面的检测还怎么做?
本章核心目标:掌握OpenCV对图像和视频的基本IO操作,为后续YOLO实时检测铺平道路。
2.1 图像读取与显示
图像读取是第一步。OpenCV用 cv2.imread() 这个函数。我个人习惯,拿到一张图先看看它到底存不存在,路径对不对。很多新手一上来就报错,十有八九是路径写错了。
import cv2
# 读取图像
img = cv2.imread('test.jpg')
# 检查是否读取成功
if img is None:
print("图像读取失败,请检查路径")
exit()
# 显示图像
cv2.imshow('My Image', img)
cv2.waitKey(0) # 等待按键
cv2.destroyAllWindows()
这里有个坑,我必须说一下。cv2.imread() 默认以BGR格式读取,不是我们常见的RGB。我曾经在项目里直接用OpenCV读图然后传给别的库处理,结果颜色全乱了。嗯,这个后面讲颜色转换时会细说。
| 参数 | 说明 | 常用值 |
|---|---|---|
filename |
图像文件路径 | 相对路径或路径 |
flags |
读取方式 | cv2.IMREAD_COLOR (默认彩色)cv2.IMREAD_GRAYSCALE (灰度)cv2.IMREAD_UNCHANGED (含Alpha通道) |
小技巧:显示图像时,cv2.waitKey(0) 表示无限等待按键。如果你想让窗口自动关闭,可以设置等待毫秒数,比如 cv2.waitKey(1000) 等待1秒。
2.2 图像属性获取
拿到图像后,我们得知道它长什么样。图像的三个基本属性:高度、宽度、通道数。用 img.shape 就能拿到。
# 获取图像属性
height, width, channels = img.shape
print(f"图像尺寸: {width} x {height}")
print(f"通道数: {channels}")
# 图像总像素数
total_pixels = img.size
print(f"总像素数: {total_pixels}")
# 图像数据类型
data_type = img.dtype
print(f"数据类型: {data_type}")
为什么要注意这些?我在做模型部署时,经常要检查输入图像的尺寸是否匹配。有一次模型要求416x416,我传进去一张1920x1080的图,结果推理直接崩了。你想想看,这种低级错误多耽误时间。
| 属性 | 代码 | 返回值示例 |
|---|---|---|
| 形状 | img.shape |
(480, 640, 3) |
| 像素总数 | img.size |
921600 |
| 数据类型 | img.dtype |
uint8 |
2.3 图像保存
处理完图像,得保存下来。用 cv2.imwrite()。这个函数会根据文件扩展名自动选择编码格式。
# 保存图像
cv2.imwrite('output.jpg', img)
# 保存为PNG格式(无损)
cv2.imwrite('output.png', img)
# 设置JPEG质量(0-100)
cv2.imwrite('output_high.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 95])
注意:cv2.imwrite() 返回布尔值,表示是否保存成功。我曾经在磁盘空间不足时没检查返回值,结果图没存下来,项目汇报时才发现。养成检查返回值的习惯。
2.4 视频读取与显示
视频其实就是一帧一帧的图像。OpenCV用 cv2.VideoCapture() 来读取视频文件。
# 打开视频文件
cap = cv2.VideoCapture('test_video.mp4')
# 检查是否打开成功
if not cap.isOpened():
print("视频打开失败")
exit()
while True:
ret, frame = cap.read()
if not ret:
print("视频读取完毕")
break
cv2.imshow('Video', frame)
# 按 'q' 键退出
if cv2.waitKey(25) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
这里 cv2.waitKey(25) 的25毫秒对应大约40FPS的播放速度。实际项目中,我会根据视频本身的帧率来调整这个值。怎么获取帧率?用 cap.get(cv2.CAP_PROP_FPS)。
2.5 摄像头初始化
终于到重点了。摄像头初始化和视频读取几乎一样,只是把文件路径换成设备ID。笔记本自带摄像头通常是0,外接USB摄像头可能是1或2。
# 初始化摄像头(0表示默认摄像头)
cap = cv2.VideoCapture(0)
# 设置摄像头参数(可选)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
cap.set(cv2.CAP_PROP_FPS, 30)
# 检查是否成功
if not cap.isOpened():
print("摄像头打开失败")
print("请检查:")
print("1. 摄像头是否连接")
print("2. 是否有其他程序占用摄像头")
print("3. 是否授予了摄像头权限")
exit()
while True:
ret, frame = cap.read()
if not ret:
print("获取帧失败")
break
# 在这里做检测处理
cv2.imshow('Camera', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
经验之谈:摄像头初始化失败最常见的原因是权限问题。Linux下要加 video 用户组,macOS要允许终端访问摄像头,Windows要检查驱动。我曾经在Docker容器里折腾了半天,最后发现是没挂载 /dev/video0 设备。
下面这张图帮你理清本章的知识脉络:
2.6 资源释放与最佳实践
最后,也是最重要的——资源管理。摄像头和视频文件都是系统资源,用完必须释放。
# 标准释放流程
cap.release() # 释放摄像头/视频
cv2.destroyAllWindows() # 关闭所有OpenCV窗口
血的教训:我曾经在写一个长时间运行的监控程序时,忘记释放摄像头资源。跑了半天后,摄像头彻底卡死,必须重启系统才能恢复。记住:cap.release() 不是可选项,是必选项。
嗯,这一章的内容就这些。看起来都是基础操作,但它们是整个课程的基石。后面的YOLO检测、实时视频处理,全都建立在这些操作之上。多练几遍,形成肌肉记忆,后面就顺手了。