一、图像显示基础与窗口控制

1.1 图像读取与显示的核心问题解析

在使用 OpenCV 处理图像时,路径问题是最常见。当路径中包含中文时,cv2.imread() 函数可能无法正确读取图像,导致后续显示操作报错。这是因为 OpenCV 底层对中文路径的支持存在兼容性问题,解决方案主要有两种:

  • 将图像路径修改为纯英文路径
  • 使用 numpy 结合 cv2.imdecode() 函数处理中文路径(进阶方案)

基础图像显示代码:

import cv2
import numpy as np

# 相对路径读取(图像与脚本在同一目录)
img = cv2.imread('10.jpg')
# 检查图像是否读取成功
if img is None:
    print("图像读取失败,请检查路径是否正确")
else:
    cv2.imshow('img', img)  # 第一个参数为窗口名称,第二个为图像数据
    cv2.waitKey(0)          # 等待用户按键,0表示无限等待
    cv2.destroyAllWindows() # 关闭所有窗口释放资源

中文路径处理方案:

import cv2
import numpy as np

# 处理中文路径的图像读取方法
def read_chinese_path(img_path):
    img_data = np.fromfile(img_path, dtype=np.uint8)
    return cv2.imdecode(img_data, cv2.IMREAD_COLOR)

# 使用中文路径读取图像
img = read_chinese_path(r'E:\素材\图片\LH照片\10.jpg')
if img is not None:
    cv2.imshow('img', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

1.2 窗口属性定制与交互控制

OpenCV 提供了灵活的窗口控制功能,通过 cv2.namedWindow() 可以创建具有特定属性的窗口:

import cv2

# 创建可调整大小的窗口
cv2.namedWindow('custom_window', cv2.WINDOW_NORMAL)  # WINDOW_NORMAL允许调整窗口大小
cv2.resizeWindow('custom_window', 800, 600)          # 设置初始窗口尺寸

# 读取并显示图像
img = cv2.imread('10.jpg')
cv2.imshow('custom_window', img)

# 等待按键并获取按键ASCII码
key = cv2.waitKey(0)
print(f"按键ASCII码:{key}")
print(f"q键的ASCII码:{ord('q')}")  # ord()函数用于获取字符的ASCII码

# 按键判断逻辑(解决跨平台兼容性问题)
if key & 0xFF == ord('q'):  # 使用0xFF屏蔽高位,确保在不同系统上结果一致
    cv2.destroyWindow('custom_window')  # 销毁指定窗口

1.3 图像交互与保存功能实现

通过循环结构实现图像的持续显示与交互控制,支持按键保存图像等操作:

import cv2

# 创建窗口并设置属性
cv2.namedWindow('interactive', cv2.WINDOW_NORMAL)
cv2.resizeWindow('interactive', 800, 600)

# 读取图像
img = cv2.imread('10.jpg')
if img is None:
    print("图像读取失败")
    exit()

# 循环显示图像,等待用户交互
while True:
    cv2.imshow('interactive', img)
    key = cv2.waitKey(0)  # 等待按键输入
    
    # 按键逻辑处理
    if key & 0xFF == ord('q'):
        # 按q键退出程序
        print("退出程序")
        break
    elif key & 0xFF == ord('s'):
        # 按s键保存图像
        save_success = cv2.imwrite('saved_image.png', img)
        if save_success:
            print("图像保存成功")
        else:
            print("图像保存失败")
    else:
        # 显示其他按键的ASCII码
        print(f"按下了键:{chr(key & 0xFF)},ASCII码:{key & 0xFF}")

# 释放所有资源
cv2.destroyAllWindows()

二、摄像头视频采集与处理

2.1 实时视频采集基础流程

使用 cv2.VideoCapture 类实现从摄像头采集实时视频:

import cv2

# 创建显示窗口
cv2.namedWindow('camera', cv2.WINDOW_AUTOSIZE)
cv2.resizeWindow('camera', 640, 480)

# 初始化摄像头(0表示默认摄像头,多个摄像头可尝试1、2等)
cap = cv2.VideoCapture(0)

# 检查摄像头是否成功打开
if not cap.isOpened():
    print("无法打开摄像头")
    exit()

# 循环读取视频帧
while True:
    # 读取一帧视频(ret为成功标志,frame为帧数据)
    ret, frame = cap.read()
    
    # 检查帧是否读取成功
    if not ret:
        print("无法获取视频帧,退出...")
        break
    
    # 显示视频帧
    cv2.imshow('camera', frame)
    
    # 等待10毫秒,检测按键(按q退出)
    key = cv2.waitKey(10)
    if key & 0xFF == ord('q'):
        break

# 释放资源
cap.release()       # 关闭摄像头
cv2.destroyAllWindows()  # 关闭所有窗口

2.2 视频采集核心函数详解

  • VideoCapture:用于初始化视频捕获对象,参数可以是:

    • 整数:摄像头索引(0表示默认摄像头)
    • 字符串:视频文件路径(用于读取本地视频)
  • cap.read() 方法

    • 返回值:(ret, frame) 元组
    • ret:布尔值,True 表示读取成功,False 表示读取失败
    • framenumpy 数组格式的图像数据(H×W×C)
  • cap.release() 方法:释放摄像头资源,必须在程序结束前调用,否则可能导致摄像头被占用无法释放

三、本地视频文件读取与播放

读取本地视频文件与读取摄像头流程类似,只需将 VideoCapture 的参数改为视频文件路径:

import cv2

# 创建显示窗口
cv2.namedWindow('video_player', cv2.WINDOW_AUTOSIZE)
cv2.resizeWindow('video_player', 640, 480)

# 打开本地视频文件(替换为实际视频路径)
cap = cv2.VideoCapture("car.mp4")

# 检查视频是否成功打开
if not cap.isOpened():
    print("无法打开视频文件")
    exit()

# 获取视频属性(可选)
fps = cap.get(cv2.CAP_PROP_FPS)  # 帧率
frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT)  # 总帧数
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)  # 帧宽度
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)  # 帧高度
print(f"视频信息:帧率{fps:.1f},总帧数{int(frame_count)},分辨率{int(width)}×{int(height)}")

# 循环播放视频
while True:
    ret, frame = cap.read()
    if not ret:
        print("视频播放完毕")
        break
    
    cv2.imshow('video_player', frame)
    
    # 控制播放速度(按原视频帧率播放)
    delay = int(1000 / fps) if fps > 0 else 10
    key = cv2.waitKey(delay)
    if key & 0xFF == ord('q'):
        break

# 释放资源
cap.release()
cv2.destroyAllWindows()

四、视频录制与保存

使用 cv2.VideoWriter 类将视频帧保存为本地文件:

import cv2

# 定义视频编码器(FourCC)
# FourCC是4字节的视频编码标识符,不同编码对应不同格式
fourcc = cv2.VideoWriter_fourcc(*'MJPG')  # MJPG编码,生成AVI格式
# 其他常用编码:
# fourcc = cv2.VideoWriter_fourcc(*'XVID')  # XVID编码,生成AVI格式
# fourcc = cv2.VideoWriter_fourcc(*'mp4v')  # MP4V编码,生成MP4格式

# 获取摄像头参数
cap = cv2.VideoCapture(0)
if not cap.isOpened():
    print("无法打开摄像头")
    exit()

# 获取摄像头实际分辨率
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS) or 25  # 若无法获取则默认25fps

# 初始化视频写入对象
out = cv2.VideoWriter(
    'recorded_video.avi',  # 输出文件名
    fourcc,                # 编码器
    fps,                   # 帧率
    (width, height)        # 帧尺寸(必须与实际帧大小一致)
)

# 创建显示窗口
cv2.namedWindow('recorder', cv2.WINDOW_AUTOSIZE)

# 录制循环
while True:
    ret, frame = cap.read()
    if not ret:
        print("无法获取视频帧")
        break
    
    # 显示当前帧
    cv2.imshow('recorder', frame)
    
    # 写入视频帧
    out.write(frame)
    
    # 按q键停止录制
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放所有资源(重要!)
cap.release()   # 释放摄像头
out.release()   # 释放视频写入器(必须调用,否则文件损坏)
cv2.destroyAllWindows()
print("视频录制完成")

4.1 视频录制常见问题解决

  1. 录制的视频无法播放

    • 检查编码器与文件扩展名是否匹配(如MJPG对应.avi,mp4v对应.mp4)
    • 确保写入的帧尺寸与 VideoWriter 初始化时的尺寸一致
  2. 视频卡顿或速度异常

    • 调整 waitKey() 的延迟时间,使其与帧率匹配
    • 降低视频分辨率减少处理压力
  3. 文件体积过大

    • 尝试使用不同的编码器(如H.264编码通常更高效)
    • 降低帧率或分辨率
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐