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 设备。

下面这张图帮你理清本章的知识脉络:

OpenCV基础操作知识体系 图像操作 读取 cv2.imread() 显示 cv2.imshow() 属性 img.shape 保存 cv2.imwrite() 视频/摄像头操作 视频文件读取 摄像头初始化 帧循环读取 参数设置 公共基础:cv2.VideoCapture() / cap.read() / cap.release() 常见避坑点 1. 检查返回值:cap.isOpened() / ret / img is None 2. 释放资源:cap.release() + cv2.destroyAllWindows()

2.6 资源释放与最佳实践

最后,也是最重要的——资源管理。摄像头和视频文件都是系统资源,用完必须释放。

# 标准释放流程
cap.release()           # 释放摄像头/视频
cv2.destroyAllWindows() # 关闭所有OpenCV窗口

血的教训:我曾经在写一个长时间运行的监控程序时,忘记释放摄像头资源。跑了半天后,摄像头彻底卡死,必须重启系统才能恢复。记住:cap.release() 不是可选项,是必选项。

嗯,这一章的内容就这些。看起来都是基础操作,但它们是整个课程的基石。后面的YOLO检测、实时视频处理,全都建立在这些操作之上。多练几遍,形成肌肉记忆,后面就顺手了。