OpenCV Python 安装与基本操作 – wiki基地


OpenCV Python 安装与基本操作:开启计算机视觉之旅

摘要: 本文旨在为 Python 开发者提供一份详尽的指南,涵盖 OpenCV 库的安装过程以及图像和视频处理的基本操作。我们将从环境准备开始,逐步介绍不同安装选项、验证方法,并深入探讨图像的读取、显示、保存、属性访问、颜色空间转换、尺寸调整、基本绘图以及视频流处理等核心功能。本文力求内容全面、步骤清晰、示例丰富,帮助读者快速入门并掌握 OpenCV 在 Python 环境下的基础应用,为后续更高级的计算机视觉任务打下坚实基础。

关键词: OpenCV, Python, 计算机视觉, 图像处理, 视频处理, 安装, 基本操作, cv2


1. 引言

计算机视觉(Computer Vision, CV)是人工智能领域的一个重要分支,其目标是使计算机能够“看懂”并解释图像和视频。OpenCV (Open Source Computer Vision Library) 是该领域最流行、功能最强大的开源库之一。它最初由 Intel 开发,现在由一个活跃的社区维护,提供了涵盖图像处理、视频分析、特征检测、对象识别、机器学习等众多领域的数千种优化算法。

Python 凭借其简洁的语法、丰富的生态系统和强大的数据处理能力,已成为与 OpenCV 结合使用的首选语言。opencv-python 包为 Python 开发者提供了便捷的接口,可以轻松调用 OpenCV 的底层 C++ 功能。

本文将聚焦于 OpenCV 在 Python 环境下的安装与基础应用。无论您是计算机视觉的新手,还是希望系统性学习 OpenCV Python 接口的开发者,本文都将为您提供必要的指导和实践示例。我们将详细介绍安装步骤,并带领您实践一系列基本操作,让您能够自信地开始使用 OpenCV 处理图像和视频。

2. 环境准备:Python 与 pip

在安装 OpenCV 之前,您需要确保您的系统已经安装了 Python 和 pip (Python 包管理器)。

2.1 检查 Python 版本

打开您的终端或命令提示符,输入以下命令:

“`bash
python –version

或者

python3 –version
“`

如果 Python 已安装,它将显示当前版本号(例如 Python 3.9.7)。OpenCV Python 通常支持较新的 Python 3.x 版本。如果未安装或版本过低,请访问 Python 官网 (python.org) 下载并安装适合您操作系统的最新稳定版本。安装时,请确保勾选 “Add Python to PATH” 或类似选项,以便在命令行中直接使用 python 命令。

2.2 检查/更新 pip

pip 通常随 Python 一起安装。检查其版本:

“`bash
pip –version

或者

pip3 –version
“`

为确保使用最新功能和最佳兼容性,建议将 pip 升级到最新版本:

“`bash
python -m pip install –upgrade pip

或者

python3 -m pip install –upgrade pip
“`

完成这些准备工作后,您的系统就具备了安装 OpenCV Python 包的基础环境。

3. 安装 OpenCV Python 包

OpenCV Python 提供了几个不同的 pip 包,以满足不同用户的需求。了解它们的区别对于选择正确的包至关重要。

3.1 主要安装选项

  • opencv-python (Main Modules): 这是最常用的包,包含了 OpenCV 的核心模块和主要功能。对于大多数标准的图像和视频处理任务,这个包已经足够。
    bash
    pip install opencv-python

  • opencv-contrib-python (Main Modules + Contrib Modules): 这个包不仅包含了 opencv-python 的所有内容,还额外包含了 “contrib” 模块。Contrib 模块包含了一些实验性的、非稳定或者受专利保护(需要注意使用许可)的算法,例如 SIFT、SURF(在较新版本中可能因专利问题移除或移至主模块)、以及一些较新的功能。如果您需要使用这些特定的高级功能,应安装此包。注意:不要同时安装 opencv-pythonopencv-contrib-python,它们会产生冲突。安装 opencv-contrib-python 会自动满足 opencv-python 的需求。
    bash
    pip install opencv-contrib-python

  • opencv-python-headless (Headless Main Modules): 这个版本与 opencv-python 类似,但不包含任何 GUI 功能(如图形窗口显示 cv2.imshow())。它适用于服务器环境、Docker 容器或其他不需要图形界面的场景,可以避免安装 GUI 相关的系统依赖库。
    bash
    pip install opencv-python-headless

  • opencv-contrib-python-headless (Headless Main + Contrib Modules): 类似于 opencv-contrib-python,但同样是 headless 版本,不包含 GUI 功能。适用于需要在无头环境中运行 contrib 模块功能的场景。
    bash
    pip install opencv-contrib-python-headless

选择建议:

  • 对于初学者和大多数桌面应用,推荐安装 opencv-contrib-python,因为它提供了最全面的功能集,方便探索各种算法。
  • 如果确定不需要 contrib 模块,并且希望安装包更小,可以选择 opencv-python
  • 如果在服务器或无 GUI 环境下运行,根据是否需要 contrib 模块,选择 opencv-python-headlessopencv-contrib-python-headless

3.2 安装过程

选择合适的包后,在终端或命令提示符中执行相应的 pip install 命令。pip 会自动下载并安装 OpenCV 包及其依赖项(主要是 NumPy,用于处理图像数据)。

“`bash

示例:安装包含 contrib 模块的版本

pip install opencv-contrib-python
“`

安装过程可能需要一些时间,具体取决于您的网络速度和系统配置。

3.3 验证安装

安装完成后,可以通过在 Python 解释器中导入 cv2 模块并检查其版本来验证安装是否成功。

打开 Python 解释器(在终端输入 pythonpython3)或创建一个 Python 脚本(例如 verify_opencv.py),输入以下代码:

“`python
import cv2

打印 OpenCV 版本号

print(f”OpenCV version: {cv2.version}”)
“`

运行脚本(python verify_opencv.py)或在解释器中执行。如果看到类似 OpenCV version: 4.x.x(具体版本号可能不同)的输出,并且没有出现 ImportError,则表示 OpenCV 已成功安装并可以在您的 Python 环境中使用了。

3.4 常见问题与解决

  • ImportError: DLL load failed (Windows): 可能是缺少 Visual C++ Redistributable。请访问微软官网下载并安装对应您 Python 版本(VC++ 2015/2017/2019/2022 通常是一个包)的 Redistributable。
  • 依赖冲突: 如果遇到与其他库(如 numpy)的版本冲突,可以尝试创建虚拟环境(使用 venvconda)来隔离项目依赖,或者尝试指定兼容的 NumPy 版本进行安装。
  • 权限问题: 在某些系统(如 Linux)上,可能需要使用 sudo 执行 pip install 命令,或者使用 --user 标志进行用户级别的安装 (pip install --user opencv-contrib-python)。

4. OpenCV 基本操作

安装成功后,我们就可以开始探索 OpenCV 的基本功能了。OpenCV 中的图像通常表示为 NumPy 数组。

4.1 读取图像 (cv2.imread)

cv2.imread() 函数用于从文件加载图像。

“`python
import cv2
import os # 用于路径操作

定义图像文件路径 (确保文件存在)

image_path = ‘path/to/your/image.jpg’ # 请替换为实际图像路径

检查文件是否存在

if not os.path.exists(image_path):
print(f”错误:图像文件未找到于 ‘{image_path}'”)
else:
# 读取图像
# 第一个参数:图像文件路径
# 第二个参数(可选):读取模式标志
# cv2.IMREAD_COLOR (默认值, 1): 加载彩色图像。任何透明度通道都会被忽略。
# cv2.IMREAD_GRAYSCALE (0): 以灰度模式加载图像。
# cv2.IMREAD_UNCHANGED (-1): 加载图像,包括 alpha (透明度) 通道(如果存在)。

# 读取彩色图像
img_color = cv2.imread(image_path, cv2.IMREAD_COLOR)

# 读取灰度图像
img_gray = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

# 检查图像是否成功加载
if img_color is None:
    print(f"错误:无法加载彩色图像 '{image_path}'。请检查路径和文件格式。")
else:
    print(f"彩色图像加载成功! 尺寸: {img_color.shape}") # shape: (height, width, channels)

if img_gray is None:
    print(f"错误:无法加载灰度图像 '{image_path}'。请检查路径和文件格式。")
else:
    print(f"灰度图像加载成功! 尺寸: {img_gray.shape}") # shape: (height, width)

“`

要点:

  • 路径: 确保提供的路径正确无误。可以使用相对路径或绝对路径。
  • 返回值: 如果图像成功加载,imread 返回一个 NumPy 数组;如果文件不存在、路径错误或文件格式不受支持/损坏,则返回 None务必在使用返回的图像对象前检查它是否为 None
  • 颜色通道顺序: OpenCV 默认以 BGR (蓝-绿-红) 顺序加载彩色图像,而不是常见的 RGB (红-绿-蓝)。这一点在与其他库(如 Matplotlib)交互时需要特别注意。

4.2 显示图像 (cv2.imshow, cv2.waitKey, cv2.destroyAllWindows)

cv2.imshow() 用于在窗口中显示图像。但仅调用 imshow 不足以让窗口保持可见,还需要配合 cv2.waitKey()cv2.destroyAllWindows()

“`python
import cv2

image_path = ‘path/to/your/image.jpg’ # 请替换为实际图像路径
img = cv2.imread(image_path)

if img is None:
print(f”错误:无法加载图像 ‘{image_path}'”)
else:
# 显示图像
# 第一个参数:窗口的名称 (字符串)
# 第二个参数:要显示的图像 (NumPy 数组)
cv2.imshow(‘My Image Window’, img)

# 等待键盘事件
# 参数:等待时间(毫秒)。
#   如果为 0,表示无限期等待,直到用户按下任意键。
#   如果为正整数 n,表示等待 n 毫秒。如果在 n 毫秒内有按键,函数返回按键的 ASCII 码;否则返回 -1。
# 这是必须的!否则图像窗口会一闪而过。
print("按任意键关闭窗口...")
key = cv2.waitKey(0) # 等待直到用户按键
print(f"按键代码: {key}") # 可以根据按键代码执行不同操作,例如按 'q' 退出

# 关闭所有由 OpenCV 创建的窗口
# 在程序结束前调用,释放资源
cv2.destroyAllWindows()

# 或者只关闭特定窗口
# cv2.destroyWindow('My Image Window')

“`

要点:

  • cv2.imshow(window_name, image): 创建或更新指定名称的窗口并显示图像。
  • cv2.waitKey(delay): 处理 GUI 事件并等待键盘输入。这是 imshow 能够正常工作的关键。没有 waitKey,图像窗口可能根本不显示或立即消失。
  • cv2.destroyAllWindows(): 关闭所有打开的 OpenCV 窗口。良好的编程习惯是在程序退出前调用它。

注意: cv2.imshow() 等 GUI 功能在 headless 版本的 OpenCV (opencv-python-headless, opencv-contrib-python-headless) 中不可用,调用会引发错误。

4.3 保存图像 (cv2.imwrite)

cv2.imwrite() 函数用于将图像(NumPy 数组)保存到文件。

“`python
import cv2
import os

image_path = ‘path/to/your/image.jpg’
output_path_color = ‘output_image_color.png’ # 保存为 PNG 格式
output_path_gray = ‘output_image_gray.jpg’ # 保存为 JPG 格式

img_color = cv2.imread(image_path, cv2.IMREAD_COLOR)
img_gray = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

if img_color is not None:
# 保存彩色图像
# 第一个参数:输出文件路径 (包含文件名和扩展名)
# 第二个参数:要保存的图像 (NumPy 数组)
# 第三个参数(可选):特定格式的参数 (例如 JPEG 质量)
# 返回值:如果保存成功,返回 True;否则返回 False。
success_color = cv2.imwrite(output_path_color, img_color)
if success_color:
print(f”彩色图像已成功保存到 ‘{output_path_color}'”)
else:
print(f”错误:无法保存彩色图像到 ‘{output_path_color}'”)

if img_gray is not None:
# 保存灰度图像,可以指定 JPEG 质量 (0-100, 默认 95)
jpeg_quality = 90
success_gray = cv2.imwrite(output_path_gray, img_gray, [cv2.IMWRITE_JPEG_QUALITY, jpeg_quality])
if success_gray:
print(f”灰度图像已成功保存到 ‘{output_path_gray}’ (JPEG 质量: {jpeg_quality})”)
else:
print(f”错误:无法保存灰度图像到 ‘{output_path_gray}'”)
“`

要点:

  • 文件格式: OpenCV 根据文件扩展名(如 .jpg, .png, .bmp, .tif 等)自动确定要使用的编码格式。
  • 参数: 可以通过可选的第三个参数传递特定于格式的设置,例如 JPEG 压缩质量 (cv2.IMWRITE_JPEG_QUALITY) 或 PNG 压缩级别 (cv2.IMWRITE_PNG_COMPRESSION)。这些参数以 [flag, value, flag, value, ...] 的列表形式提供。

4.4 访问图像属性

加载后的图像是 NumPy 数组,可以访问其属性来获取信息:

“`python
import cv2

image_path = ‘path/to/your/image.jpg’
img_color = cv2.imread(image_path, cv2.IMREAD_COLOR)
img_gray = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

if img_color is not None:
# 获取彩色图像的维度 (shape)
# 返回一个元组:(高度, 宽度, 通道数)
height, width, channels = img_color.shape
print(f”彩色图像 – 高度: {height}px, 宽度: {width}px, 通道数: {channels}”)

# 获取图像的总像素数
total_pixels_color = img_color.size
print(f"彩色图像 - 总像素数: {total_pixels_color}") # 等于 height * width * channels

# 获取图像数据类型
# 通常是 uint8 (无符号 8 位整数,范围 0-255)
data_type_color = img_color.dtype
print(f"彩色图像 - 数据类型: {data_type_color}")

if img_gray is not None:
# 获取灰度图像的维度
# 返回一个元组:(高度, 宽度) – 注意,没有通道维度
height_g, width_g = img_gray.shape
print(f”灰度图像 – 高度: {height_g}px, 宽度: {width_g}px”)

# 获取总像素数
total_pixels_gray = img_gray.size
print(f"灰度图像 - 总像素数: {total_pixels_gray}") # 等于 height * width

# 获取数据类型
data_type_gray = img_gray.dtype
print(f"灰度图像 - 数据类型: {data_type_gray}")

# 访问特定像素值 (示例:访问坐标 (100, 50) 的像素)
# 注意:坐标顺序是 (y, x) 或 (row, column)
if height > 100 and width > 50:
    pixel_value_color = img_color[100, 50] # 返回一个 BGR 值数组,例如 [blue, green, red]
    print(f"彩色图像 (100, 50) 处的 BGR 值: {pixel_value_color}")

if height_g > 100 and width_g > 50:
    pixel_value_gray = img_gray[100, 50] # 返回一个灰度值 (0-255)
    print(f"灰度图像 (100, 50) 处的灰度值: {pixel_value_gray}")

“`

要点:

  • shape: 返回图像维度。对于彩色图像是 (height, width, channels),对于灰度图像是 (height, width)
  • size: 返回图像包含的元素总数(像素值)。
  • dtype: 返回数组元素的数据类型,通常是 uint8
  • 像素访问: 可以使用 NumPy 的索引方式 img[y, x] 来访问或修改特定像素的值。记住坐标顺序是 (行/高, 列/宽)。对于彩色图像,img[y, x] 返回一个包含 BGR 值的数组/列表。

4.5 颜色空间转换 (cv2.cvtColor)

OpenCV 提供了在不同颜色空间之间转换的功能,最常用的是 BGR 与 Grayscale 以及 BGR 与 RGB 之间的转换。

“`python
import cv2
import matplotlib.pyplot as plt # 用于显示 RGB 图像

image_path = ‘path/to/your/image.jpg’
img_bgr = cv2.imread(image_path)

if img_bgr is None:
print(f”错误:无法加载图像 ‘{image_path}'”)
else:
# 1. BGR 转换为 Grayscale (灰度图)
img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
cv2.imshow(‘Grayscale Image’, img_gray)
cv2.imwrite(‘output_grayscale.jpg’, img_gray)

# 2. BGR 转换为 RGB
# 这在需要将 OpenCV 图像传递给其他默认使用 RGB 的库(如 Matplotlib)时非常重要
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)

# 使用 Matplotlib 显示 RGB 图像
plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1)
plt.imshow(img_bgr) # 直接用 plt 显示 BGR 会颜色失真
plt.title('BGR Image (Displayed with Matplotlib)')
plt.axis('off')

plt.subplot(1, 2, 2)
plt.imshow(img_rgb) # 显示转换后的 RGB 图像,颜色正常
plt.title('RGB Image (Converted from BGR)')
plt.axis('off')

plt.tight_layout()
plt.show() # Matplotlib 的显示方法

# 3. BGR 转换为 HSV (Hue, Saturation, Value)
# HSV 颜色空间常用于颜色检测和分割
img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)
cv2.imshow('HSV Image', img_hsv)
# 注意:直接显示 HSV 图像可能看起来不直观

print("按任意键关闭 OpenCV 窗口...")
cv2.waitKey(0)
cv2.destroyAllWindows()

“`

要点:

  • cv2.cvtColor(source_image, conversion_code): 是主要的颜色转换函数。
  • conversion_code: 是指定转换类型的标志,例如:
    • cv2.COLOR_BGR2GRAY: BGR 到灰度
    • cv2.COLOR_BGR2RGB: BGR 到 RGB
    • cv2.COLOR_RGB2BGR: RGB 到 BGR
    • cv2.COLOR_BGR2HSV: BGR 到 HSV
    • cv2.COLOR_HSV2BGR: HSV 到 BGR
    • 还有许多其他转换,如 LAB, YCrCb 等。
  • BGR vs RGB: 务必记住 OpenCV 使用 BGR,而许多其他库(如 Matplotlib, Pillow)使用 RGB。在库之间传递图像时,通常需要进行 cv2.COLOR_BGR2RGBcv2.COLOR_RGB2BGR 转换。

4.6 调整图像尺寸 (cv2.resize)

改变图像的大小是常见的预处理步骤。

“`python
import cv2

image_path = ‘path/to/your/image.jpg’
img = cv2.imread(image_path)

if img is None:
print(f”错误:无法加载图像 ‘{image_path}'”)
else:
height, width = img.shape[:2]
print(f”原始尺寸: {width}x{height}”)

# 1. 缩放到固定尺寸 (指定宽度和高度)
new_width = 300
new_height = 200
# 注意:目标尺寸参数是 (宽度, 高度)
resized_fixed = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_LINEAR)
print(f"固定尺寸缩放后: {resized_fixed.shape[1]}x{resized_fixed.shape[0]}")
cv2.imshow('Resized Fixed', resized_fixed)

# 2. 按比例缩放 (例如,缩小到原来的 50%)
scale_percent = 50 # 缩放因子 (%)
scaled_width = int(width * scale_percent / 100)
scaled_height = int(height * scale_percent / 100)
# 目标尺寸仍然是 (宽度, 高度)
resized_scaled = cv2.resize(img, (scaled_width, scaled_height), interpolation=cv2.INTER_AREA)
print(f"比例缩放后 ({scale_percent}%): {resized_scaled.shape[1]}x{resized_scaled.shape[0]}")
cv2.imshow('Resized Scaled', resized_scaled)

# interpolation 参数(插值方法):
#   cv2.INTER_NEAREST: 最近邻插值 (速度快,效果差)
#   cv2.INTER_LINEAR: 双线性插值 (默认,常用,效果和速度均衡)
#   cv2.INTER_AREA: 基于区域的重采样。适用于图像缩小,可以避免波纹。
#   cv2.INTER_CUBIC: 双三次插值 (效果较好,尤其放大时,但速度较慢)
#   cv2.INTER_LANCZOS4: Lanczos 插值 (效果最好,速度最慢)
# 选择建议:缩小用 INTER_AREA,放大用 INTER_CUBIC 或 INTER_LINEAR。

cv2.waitKey(0)
cv2.destroyAllWindows()

“`

要点:

  • cv2.resize(source_image, dsize, fx=0, fy=0, interpolation=cv2.INTER_LINEAR):
    • dsize: 目标尺寸,格式为 (width, height) 元组。注意宽度在前!
    • fx, fy: 沿水平和垂直方向的缩放因子。如果指定了 dsize,则忽略 fxfy。如果 dsize(0, 0),则尺寸通过 fxfy 计算 (new_width = width * fx, new_height = height * fy)。
    • interpolation: 插值算法,影响调整尺寸后的图像质量和速度。

4.7 绘制基本形状和文本

OpenCV 允许在图像上绘制线条、矩形、圆、椭圆、多边形和添加文本,这对于可视化、标注等很有用。注意:绘图函数通常会直接修改原始图像(in-place操作)。如果不想改变原图,应先创建副本 (img_copy = img.copy())。

“`python
import cv2
import numpy as np

创建一个黑色背景图像用于演示

height, width = 400, 600

np.zeros 创建一个填充为 0 的数组 (黑色)

(height, width, 3) 表示 3 通道 (BGR)

dtype=np.uint8 表示 8 位无符号整数 (0-255)

canvas = np.zeros((height, width, 3), dtype=np.uint8)

定义颜色 (BGR 格式)

blue = (255, 0, 0)
green = (0, 255, 0)
red = (0, 0, 255)
white = (255, 255, 255)

1. 绘制线条 cv2.line()

参数:图像, 起点(x1, y1), 终点(x2, y2), 颜色, 线条粗细(thickness)

start_point = (50, 50)
end_point = (250, 150)
cv2.line(canvas, start_point, end_point, green, thickness=3)

2. 绘制矩形 cv2.rectangle()

参数:图像, 左上角顶点(x1, y1), 右下角顶点(x2, y2), 颜色, 粗细

如果粗细为 -1, 则填充矩形

top_left = (300, 50)
bottom_right = (500, 200)
cv2.rectangle(canvas, top_left, bottom_right, blue, thickness=2) # 绘制边框
cv2.rectangle(canvas, (50, 200), (150, 300), red, thickness=-1) # 填充矩形

3. 绘制圆形 cv2.circle()

参数:图像, 圆心(center_x, center_y), 半径(radius), 颜色, 粗细 (-1 填充)

center = (400, 300)
radius = 50
cv2.circle(canvas, center, radius, white, thickness=-1) # 填充白色圆

4. 添加文本 cv2.putText()

参数:图像, 文本内容(string), 左下角起点(org_x, org_y), 字体类型, 字体大小(scale), 颜色, 粗细, 线条类型(可选)

text = “OpenCV Basics”
org = (50, 370) # 文本的左下角坐标
font = cv2.FONT_HERSHEY_SIMPLEX # 选择一种字体
font_scale = 1
font_thickness = 2
cv2.putText(canvas, text, org, font, font_scale, green, font_thickness, cv2.LINE_AA) # LINE_AA 提供抗锯齿效果

显示绘制结果

cv2.imshow(“Drawing Canvas”, canvas)
cv2.imwrite(“drawing_output.png”, canvas)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`

要点:

  • 坐标系统: OpenCV 的坐标原点 (0,0) 在图像的左上角,x 轴向右,y 轴向下。点坐标通常表示为 (x, y)
  • 颜色: 颜色参数通常是一个 BGR 元组 (Blue, Green, Red),每个值的范围是 0-255。
  • 粗细 (Thickness): 对于线条、矩形、圆等,正值表示边框粗细。-1 通常表示填充形状。
  • 字体: OpenCV 提供多种内置字体(如 cv2.FONT_HERSHEY_SIMPLEX, cv2.FONT_HERSHEY_PLAIN 等)。
  • In-place 修改: 再次强调,绘图函数直接作用于传入的图像 NumPy 数组。

4.8 处理视频流

OpenCV 不仅能处理静态图像,还能轻松处理视频文件或实时摄像头流。

4.8.1 从摄像头读取视频

“`python
import cv2

打开默认摄像头 (通常索引为 0)

如果有多个摄像头,可以尝试 1, 2, …

cap = cv2.VideoCapture(0)

检查摄像头是否成功打开

if not cap.isOpened():
print(“错误:无法打开摄像头”)
exit()

print(“按 ‘q’ 键退出…”)

while True:
# 按帧读取视频
# cap.read() 返回两个值:
# 1. ret: 布尔值,表示是否成功读取到帧 (True 表示成功)
# 2. frame: 读取到的视频帧 (一个 NumPy 数组图像)
ret, frame = cap.read()

# 如果无法读取帧 (例如摄像头断开或视频结束),则退出循环
if not ret:
    print("无法接收帧 (视频流结束?). Exiting ...")
    break

# (可选) 在这里可以对 frame 进行各种处理,例如:
# gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# cv2.imshow('Grayscale Feed', gray_frame)

# 显示原始彩色帧
cv2.imshow('Camera Feed', frame)

# 等待按键事件 (例如等待 1 毫秒)
# 如果按下 'q' 键 (ASCII 值为 ord('q')),则退出循环
if cv2.waitKey(1) == ord('q'):
    break

操作完成后,释放摄像头资源

cap.release()

关闭所有 OpenCV 窗口

cv2.destroyAllWindows()
“`

4.8.2 从视频文件读取

处理视频文件与处理摄像头类似,只需将 cv2.VideoCapture() 的参数改为视频文件路径。

“`python
import cv2

video_path = ‘path/to/your/video.mp4’ # 请替换为实际视频路径
cap = cv2.VideoCapture(video_path)

if not cap.isOpened():
print(f”错误:无法打开视频文件 ‘{video_path}'”)
exit()

获取视频的一些属性 (可选)

fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
print(f”视频信息 – FPS: {fps}, 尺寸: {width}x{height}”)

print(“播放视频… 按 ‘q’ 键或视频结束时退出。”)

while True:
ret, frame = cap.read()

if not ret:
    print("视频播放完毕或读取错误.")
    break

# 显示当前帧
cv2.imshow('Video Player', frame)

# 控制播放速度:waitKey 的参数可以调整
# waitKey(int(1000/fps)) 可以尝试接近原始帧率播放,但不精确
# waitKey(25) 大约是 40fps 的延迟
if cv2.waitKey(25) == ord('q'):
    break

释放视频文件句柄

cap.release()
cv2.destroyAllWindows()
“`

要点:

  • cv2.VideoCapture(source): 创建一个视频捕获对象。source 可以是设备索引(整数,如 0)或视频文件路径(字符串)。
  • cap.isOpened(): 检查视频源是否成功打开。
  • cap.read(): 读取下一帧。返回 (ret, frame)必须检查 ret 是否为 True
  • cap.get(property_id): 获取视频属性,如帧率 (cv2.CAP_PROP_FPS)、宽度 (cv2.CAP_PROP_FRAME_WIDTH)、高度 (cv2.CAP_PROP_FRAME_HEIGHT) 等。
  • cap.release(): 非常重要! 在使用完视频源后,必须调用此方法释放资源。

5. 综合示例:读取、处理、绘制与显示

下面是一个简单的脚本,结合了前面学到的多种操作:

“`python
import cv2
import numpy as np

def process_image(image_path):
“””加载图像,转换为灰度,绘制矩形和文本,并显示结果。”””
# 1. 读取图像
img_bgr = cv2.imread(image_path, cv2.IMREAD_COLOR)
if img_bgr is None:
print(f”错误:无法加载图像 ‘{image_path}'”)
return

# 创建副本以进行绘制,保留原始图像
img_display = img_bgr.copy()

# 2. 获取图像尺寸
height, width = img_display.shape[:2]
print(f"图像尺寸: {width}x{height}")

# 3. 转换为灰度图
img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)

# 4. 在彩色副本上绘制一个矩形
top_left = (int(width * 0.1), int(height * 0.1)) # 左上角在 10% 的位置
bottom_right = (int(width * 0.9), int(height * 0.9)) # 右下角在 90% 的位置
rect_color = (0, 255, 0) # 绿色
rect_thickness = 2
cv2.rectangle(img_display, top_left, bottom_right, rect_color, rect_thickness)

# 5. 在彩色副本上添加文本
text = f"Size: {width}x{height}"
org = (top_left[0], top_left[1] - 10) # 在矩形上方一点的位置
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 0.7
text_color = (0, 0, 255) # 红色
text_thickness = 2
cv2.putText(img_display, text, org, font, font_scale, text_color, text_thickness, cv2.LINE_AA)

# 6. 显示原始图像、灰度图像和处理后的图像
cv2.imshow('Original Image', img_bgr)
cv2.imshow('Grayscale Image', img_gray)
cv2.imshow('Processed Image', img_display)

# 7. 保存处理后的图像
output_filename = "processed_" + os.path.basename(image_path)
cv2.imwrite(output_filename, img_display)
print(f"处理后的图像已保存为 '{output_filename}'")

# 8. 等待用户按键后关闭窗口
print("按任意键关闭所有窗口...")
cv2.waitKey(0)
cv2.destroyAllWindows()

— 主程序 —

if name == “main“:
import os
# 使用一个示例图像路径 (请确保该路径有效或替换为您自己的图像)
# 可以尝试网上找一张图片保存下来测试
default_image_path = ‘sample_image.jpg’ # 替换为你的图片

# 检查默认图片是否存在,如果不存在,提示用户
if not os.path.exists(default_image_path):
    print(f"警告:默认图片 '{default_image_path}' 不存在。")
    # 可以在这里尝试下载一张图片或直接退出
    # 示例:下载一张图片 (需要 requests 库: pip install requests)
    try:
        import requests
        print("尝试下载示例图片...")
        url = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg" # 示例图片 URL
        response = requests.get(url, stream=True)
        if response.status_code == 200:
            with open(default_image_path, 'wb') as f:
                for chunk in response.iter_content(1024):
                    f.write(chunk)
            print(f"示例图片已下载为 '{default_image_path}'")
        else:
            print("下载失败。请手动提供一张图片。")
            exit()
    except ImportError:
        print("未安装 'requests' 库,无法自动下载图片。请手动提供一张图片。")
        exit()
    except Exception as e:
        print(f"下载图片时出错: {e}")
        exit()

process_image(default_image_path)

“`

6. 进阶学习方向

掌握了 OpenCV 的基本操作后,您可以探索更多激动人心的领域:

  • 图像滤波与增强: 模糊(高斯模糊、均值模糊)、锐化、边缘检测(Sobel, Canny)、形态学操作(腐蚀、膨胀)。
  • 特征检测与匹配: SIFT, SURF, ORB, AKAZE 等用于寻找图像中的关键点,并进行匹配,可用于图像拼接、目标识别等。
  • 对象检测: 使用 Haar 级联分类器、HOG 特征或基于深度学习的模型(如 YOLO, SSD, Faster R-CNN)来定位图像中的特定对象(如人脸、行人、车辆)。
  • 视频分析: 目标跟踪(MeanShift, CamShift, KCF, CSRT)、光流法。
  • 相机标定与三维重建: 校正相机畸变,估计相机参数,进行立体视觉和三维场景重建。
  • 机器学习与深度学习集成: 利用 OpenCV 内置的机器学习模块(如 SVM, K-Means)或将其与 TensorFlow, PyTorch 等深度学习框架结合,实现更复杂的视觉任务。

7. 总结

OpenCV 是一个功能极其丰富的计算机视觉库,而 Python 则为其提供了易于使用的接口。本文详细介绍了在 Python 环境下安装 OpenCV 的不同选项和验证方法,并深入探讨了图像和视频处理的基础操作,包括读取、显示、保存、属性访问、颜色空间转换、尺寸调整、基本绘图以及视频流的捕获与处理。

通过实践这些基本操作,您已经迈出了使用 OpenCV 进行计算机视觉开发的第一步。理解图像如何表示为 NumPy 数组以及各种核心函数的使用方法,是掌握更高级技术的基础。希望本文能为您打开计算机视觉世界的大门,并激发您继续探索图像和视频分析的无限可能。不断实践,参考官方文档,并尝试解决实际问题,是提升技能的最佳途径。祝您在计算机视觉的旅程中一帆风顺!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部