如何使用OpenCV-Python进行图像处理?

使用 OpenCV-Python 进行图像处理的详尽指南

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库。它包含了超过2500种优化算法,可用于各种图像和视频处理任务。OpenCV 跨平台支持,可以在 Windows、Linux、macOS、iOS 和 Android 上运行。OpenCV 提供了多种语言的接口,包括 C++、Java 和 Python。其中,OpenCV-Python 是 OpenCV 的 Python API,它结合了 OpenCV C++ API 的高效性和 Python 语言的易用性。

本文将深入探讨如何使用 OpenCV-Python(通常简称为 cv2)进行各种图像处理操作。我们将从基础的图像读取和显示开始,逐步深入到更高级的技术,如滤波、边缘检测、形态学操作、特征检测、对象跟踪等。

1. 安装 OpenCV-Python

最简单的安装方法是使用 pip:

bash
pip install opencv-python

如果你需要包含一些额外的贡献模块(例如 SIFT、SURF 等,这些模块可能受专利保护),可以使用:

bash
pip install opencv-contrib-python

2. 基础图像操作

2.1 读取图像

使用 cv2.imread() 函数读取图像文件。它接受两个参数:

  • 文件名(包括路径):指定要读取的图像文件的路径。
  • 标志(可选):指定图像读取模式。常见的标志有:
    • cv2.IMREAD_COLOR (或 1): 默认值,加载彩色图像(忽略透明度通道)。
    • cv2.IMREAD_GRAYSCALE (或 0): 加载灰度图像。
    • cv2.IMREAD_UNCHANGED (或 -1): 加载图像,包括透明度通道(如果有)。

```python
import cv2

读取彩色图像

img_color = cv2.imread('image.jpg', cv2.IMREAD_COLOR)

读取灰度图像

img_gray = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

读取图像,包括透明度通道

img_unchanged = cv2.imread('image.png', cv2.IMREAD_UNCHANGED)

检查是否成功读取

if img_color is None:
print("Error: Could not read the image.")
```

2.2 显示图像

使用 cv2.imshow() 函数显示图像。它接受两个参数:

  • 窗口名称:一个字符串,用作显示图像的窗口的标题。
  • 图像:要显示的图像(NumPy 数组)。

cv2.imshow() 通常与 cv2.waitKey()cv2.destroyAllWindows() 结合使用:

  • cv2.waitKey(delay): 等待指定的毫秒数,直到按下键盘上的任意键。如果 delay 为 0,则无限期等待。
  • cv2.destroyAllWindows(): 销毁所有打开的 OpenCV 窗口。
  • cv2.destroyWindow(windowName): 销毁指定名称的窗口。

```python
import cv2

img = cv2.imread('image.jpg')

if img is not None:
cv2.imshow('Image', img) # 显示图像,窗口标题为 'Image'
cv2.waitKey(0) # 等待按键,无限期
cv2.destroyAllWindows() # 关闭所有窗口
```

2.3 保存图像

使用 cv2.imwrite() 函数保存图像。它接受两个参数:

  • 文件名:要保存的图像文件的路径和名称(包括扩展名)。
  • 图像:要保存的图像(NumPy 数组)。

```python
import cv2

img = cv2.imread('image.jpg')

if img is not None:
cv2.imwrite('output.png', img) # 将图像保存为 PNG 格式
```

2.4 图像属性

图像在 OpenCV 中表示为 NumPy 数组。你可以通过以下属性访问图像的属性:

  • img.shape: 返回一个元组,表示图像的尺寸(高度、宽度、通道数)。
    • 对于灰度图像,通道数为 1。
    • 对于彩色图像(BGR 格式),通道数为 3。
  • img.size: 返回图像的总像素数(高度 * 宽度 * 通道数)。
  • img.dtype: 返回图像的数据类型(例如 uint8float32 等)。

python
import cv2
img = cv2.imread('image.jpg')
if img is not None:
print("Shape:", img.shape) # 输出: (高度, 宽度, 通道数)
print("Size:", img.size) # 输出: 总像素数
print("Data type:", img.dtype) # 输出: 数据类型

3. 色彩空间转换

OpenCV 默认以 BGR(蓝、绿、红)颜色空间读取图像。你可以使用 cv2.cvtColor() 函数在不同的色彩空间之间进行转换。常见的色彩空间转换包括:

  • BGR 到灰度:cv2.COLOR_BGR2GRAY
  • BGR 到 HSV:cv2.COLOR_BGR2HSV
  • BGR 到 RGB:cv2.COLOR_BGR2RGB
  • RGB 到 BGR:cv2.COLOR_RGB2BGR (在某些情况下可能需要, 比如你使用了matplotlib)

```python
import cv2

img = cv2.imread('image.jpg')

if img is not None:
# BGR 到灰度
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# BGR 到 HSV
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# BGR 到 RGB (如果你需要 RGB 格式)
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

cv2.imshow('Gray Image', gray_img)
cv2.imshow('HSV Image', hsv_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
```

4. 几何变换

4.1 缩放

使用 cv2.resize() 函数调整图像大小。

```python
import cv2

img = cv2.imread('image.jpg')
if img is not None:
# 缩放到指定的宽度和高度
resized_img = cv2.resize(img, (500, 400)) # 宽度 500, 高度 400

# 按比例缩放
scaled_img = cv2.resize(img, None, fx=0.5, fy=0.5)  # 缩小一半

cv2.imshow('Resized Image', resized_img)
cv2.imshow('Scaled Image', scaled_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

```

4.2 平移

平移是沿 x 和 y 轴移动图像。你可以使用仿射变换来实现平移。

```python
import cv2
import numpy as np

img = cv2.imread('image.jpg')
if img is not None:
rows, cols, _ = img.shape

# 定义平移矩阵
M = np.float32([[1, 0, 50], [0, 1, 30]])  # 向右移动 50 像素, 向下移动 30 像素

# 应用仿射变换
translated_img = cv2.warpAffine(img, M, (cols, rows))

cv2.imshow('Translated Image', translated_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

```

4.3 旋转

旋转也是一种仿射变换。OpenCV 提供了 cv2.getRotationMatrix2D() 函数来生成旋转矩阵。

```python
import cv2
import numpy as np

img = cv2.imread('image.jpg')

if img is not None:
rows, cols, _ = img.shape

# 获取旋转矩阵 (中心点, 旋转角度, 缩放因子)
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 45, 1)  # 以图像中心旋转 45 度

# 应用仿射变换
rotated_img = cv2.warpAffine(img, M, (cols, rows))

cv2.imshow('Rotated Image', rotated_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

```

4.4 仿射变换

仿射变换是保持图像中直线和平行性的变换。你可以使用 cv2.getAffineTransform() 通过指定三个点的对应关系来创建仿射变换矩阵。

```python
import cv2
import numpy as np
img = cv2.imread('image.jpg')

if img is not None:
rows, cols, ch = img.shape
# 原图像中的三个点
pts1 = np.float32([[50,50],[200,50],[50,200]])
# 变换后图像中对应的三个点
pts2 = np.float32([[10,100],[200,50],[100,250]])

# 生成仿射变换矩阵
M = cv2.getAffineTransform(pts1,pts2)

# 应用仿射变换
dst = cv2.warpAffine(img,M,(cols,rows))

cv2.imshow('Affine Transform', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

```
4.5 透视变换

透视变换可以改变图像的视角。你可以使用 cv2.getPerspectiveTransform() 通过指定四个点的对应关系来创建透视变换矩阵, 然后使用 cv2.warpPerspective() 应用变换。

```python
import cv2
import numpy as np

img = cv2.imread('image.jpg')
if img is not None:
rows, cols, ch = img.shape

# 原图像中的四个点
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
# 变换后图像中对应的四个点
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])

# 生成透视变换矩阵
M = cv2.getPerspectiveTransform(pts1,pts2)

# 应用透视变换
dst = cv2.warpPerspective(img,M,(300,300))

cv2.imshow('Perspective Transform', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

```

5. 图像阈值处理

阈值处理是将图像分割成不同区域的常用方法。OpenCV 提供了 cv2.threshold() 函数和 cv2.adaptiveThreshold() 函数。

5.1 cv2.threshold()

cv2.threshold() 函数应用固定级别的阈值。

```python
import cv2

img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

if img is not None:
# 二值化阈值处理 (大于阈值的像素设为 255, 小于阈值的像素设为 0)
ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)

# 反二值化阈值处理 (大于阈值的像素设为 0, 小于阈值的像素设为 255)
ret, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)

# 截断阈值处理 (大于阈值的像素设为阈值, 小于阈值的像素保持不变)
ret, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)

# 阈值处理为 0 (小于阈值的像素设为 0, 大于阈值的像素保持不变)
ret, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)

# 反阈值处理为 0 (大于阈值的像素设为 0, 小于阈值的像素保持不变)
ret, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)
cv2.imshow('Original', img)
cv2.imshow('Binary', thresh1)
cv2.imshow('Binary Inv', thresh2)
cv2.imshow('Trunc', thresh3)
cv2.imshow('To Zero', thresh4)
cv2.imshow('To Zero Inv', thresh5)
cv2.waitKey(0)
cv2.destroyAllWindows()
```

5.2 cv2.adaptiveThreshold()

cv2.adaptiveThreshold() 函数根据图像局部区域的特性自适应地计算阈值。

```python
import cv2

img = cv2.imread('sudoku.jpg', cv2.IMREAD_GRAYSCALE) # 使用一张有明暗变化的图片

if img is not None:
# 中值滤波 (去除椒盐噪声)
img = cv2.medianBlur(img, 5)

# 自适应阈值处理 (均值方法)
thresh1 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, \
cv2.THRESH_BINARY, 11, 2)

# 自适应阈值处理 (高斯方法)
thresh2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, \
cv2.THRESH_BINARY, 11, 2)

cv2.imshow('Original', img)
cv2.imshow('Adaptive Mean', thresh1)
cv2.imshow('Adaptive Gaussian', thresh2)
cv2.waitKey(0)
cv2.destroyAllWindows()
```

6. 图像平滑(滤波)

图像平滑(或模糊)用于减少图像中的噪声和细节。OpenCV 提供了多种滤波器。

6.1 均值滤波

cv2.blur()cv2.boxFilter()

python
import cv2
img = cv2.imread('noisy_image.jpg')
if img is not None:
# 使用 5x5 均值滤波器
blur = cv2.blur(img, (5, 5))
cv2.imshow('Original', img)
cv2.imshow('Blurred', blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

6.2 高斯滤波

cv2.GaussianBlur()

python
import cv2
img = cv2.imread('noisy_image.jpg')
if img is not None:
# 使用 5x5 高斯滤波器, 标准差为 0 (自动计算)
gaussian_blur = cv2.GaussianBlur(img, (5, 5), 0)
cv2.imshow('Original', img)
cv2.imshow('Gaussian Blurred', gaussian_blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

6.3 中值滤波

cv2.medianBlur() (对椒盐噪声特别有效)

```python
import cv2
img = cv2.imread('salt_pepper_noise.jpg') # 加载有椒盐噪声的图像
if img is not None:
# 使用 5x5 中值滤波器
median_blur = cv2.medianBlur(img, 5)
cv2.imshow('Original', img)
cv2.imshow('Median Blurred', median_blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

```

6.4 双边滤波

cv2.bilateralFilter() (在保持边缘清晰的同时平滑图像)

python
import cv2
img = cv2.imread('image.jpg')
if img is not None:
# 使用双边滤波器 (直径, 颜色空间标准差, 坐标空间标准差)
bilateral_filtered = cv2.bilateralFilter(img, 9, 75, 75)
cv2.imshow('Original', img)
cv2.imshow('Bilateral Filtered', bilateral_filtered)
cv2.waitKey(0)
cv2.destroyAllWindows()

7. 形态学操作

形态学操作是基于图像形状的一组图像处理操作。它们通常用于二值图像(例如,阈值处理后的图像),但也可以用于灰度图像。

7.1 腐蚀

cv2.erode() (缩小前景对象的边界)

```python
import cv2
import numpy as np

img = cv2.imread('j.png', cv2.IMREAD_GRAYSCALE) # 使用一个简单的二值图像
if img is not None:
# 创建一个 5x5 的矩形结构元素
kernel = np.ones((5, 5), np.uint8)

# 应用腐蚀
erosion = cv2.erode(img, kernel, iterations=1)

cv2.imshow('Original', img)
cv2.imshow('Erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()

```

7.2 膨胀

cv2.dilate() (扩大前景对象的边界)

```python
import cv2
import numpy as np

img = cv2.imread('j.png', cv2.IMREAD_GRAYSCALE)
if img is not None:
# 创建一个 5x5 的矩形结构元素
kernel = np.ones((5, 5), np.uint8)

# 应用膨胀
dilation = cv2.dilate(img, kernel, iterations=1)

cv2.imshow('Original', img)
cv2.imshow('Dilation', dilation)
cv2.waitKey(0)
cv2.destroyAllWindows()

```

7.3 开运算

cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) (先腐蚀后膨胀,用于去除小的对象或噪声)

```python
import cv2
import numpy as np

img = cv2.imread('opening.png', cv2.IMREAD_GRAYSCALE) # 使用一个包含小噪声的图像
if img is not None:
# 创建一个 5x5 的矩形结构元素
kernel = np.ones((5, 5), np.uint8)

# 应用开运算
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

cv2.imshow('Original', img)
cv2.imshow('Opening', opening)
cv2.waitKey(0)
cv2.destroyAllWindows()

```

7.4 闭运算

cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) (先膨胀后腐蚀,用于填充小的孔洞)

```python
import cv2
import numpy as np

img = cv2.imread('closing.png', cv2.IMREAD_GRAYSCALE) # 使用一个包含小孔洞的图像

if img is not None:
# 创建一个 5x5 的矩形结构元素
kernel = np.ones((5, 5), np.uint8)

# 应用闭运算
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

cv2.imshow('Original', img)
cv2.imshow('Closing', closing)
cv2.waitKey(0)
cv2.destroyAllWindows()

```

7.5 形态学梯度

cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel) (膨胀和腐蚀之间的差,用于提取对象的边缘)

7.6 顶帽

cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) (原图像与开运算结果的差,用于提取比周围更亮的区域)

7.7 黑帽

cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel) (闭运算结果与原图像的差,用于提取比周围更暗的区域)

8. 边缘检测

边缘检测用于识别图像中亮度变化明显的区域。

8.1 Sobel 算子

cv2.Sobel() (计算图像在 x 和 y 方向上的梯度)

```python
import cv2

img = cv2.imread('sudoku.jpg', cv2.IMREAD_GRAYSCALE)
if img is not None:
# 计算 x 方向上的梯度 (垂直边缘)
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)

# 计算 y 方向上的梯度 (水平边缘)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)

# 计算梯度幅值
abs_grad_x = cv2.convertScaleAbs(sobelx)
abs_grad_y = cv2.convertScaleAbs(sobely)
grad = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)

cv2.imshow('Original', img)
cv2.imshow('Sobel X', abs_grad_x)
cv2.imshow('Sobel Y', abs_grad_y)
cv2.imshow('Sobel Combined', grad)

cv2.waitKey(0)
cv2.destroyAllWindows()

```
8.2 Scharr 算子

cv2.Scharr() Sobel算子的增强版, 对细小边缘更敏感

8.3 Laplacian 算子

cv2.Laplacian() (计算图像的二阶导数,对边缘更敏感)

```python
import cv2
img = cv2.imread('sudoku.jpg', cv2.IMREAD_GRAYSCALE)

if img is not None:
# 计算 Laplacian 梯度
laplacian = cv2.Laplacian(img, cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian) # 需要转回 uint8 才能显示

cv2.imshow('Original', img)
cv2.imshow('Laplacian', laplacian)
cv2.waitKey(0)
cv2.destroyAllWindows()

```

8.4 Canny 边缘检测

cv2.Canny() (一种多阶段的边缘检测算法,效果通常更好)

```python
import cv2
img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
if img is not None:
# 使用 Canny 边缘检测 (低阈值, 高阈值)
edges = cv2.Canny(img, 100, 200)

cv2.imshow('Original', img)
cv2.imshow('Canny Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

```

9. 轮廓检测

轮廓检测用于查找图像中对象的边界。

```python
import cv2
img = cv2.imread('shapes.png') # 使用一个包含多个形状的图像
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

if img is not None:
# 阈值处理 (将图像二值化)
ret, thresh = cv2.threshold(img_gray, 127, 255, 0)

# 查找轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# contours 是一个列表, 包含所有找到的轮廓
# hierarchy 包含轮廓的层级关系

# 绘制轮廓
cv2.drawContours(img, contours, -1, (0, 255, 0), 3) # -1 表示绘制所有轮廓, (0,255,0) 是绿色, 3 是线宽

cv2.imshow('Contours', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

```

10. 直方图

直方图是图像中像素强度分布的图形表示。

10.1 计算直方图

cv2.calcHist()

```python
import cv2
import matplotlib.pyplot as plt # 导入 matplotlib 用于绘图

img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
if img is not None:
# 计算直方图 ([图像], [通道], 掩码, [直方图大小], [像素范围])
hist = cv2.calcHist([img], [0], None, [256], [0, 256])

# 使用 matplotlib 绘制直方图
plt.plot(hist)
plt.show()

```

10.2 直方图均衡化

cv2.equalizeHist() (增强图像的对比度)

```python
import cv2
img = cv2.imread('low_contrast.jpg', cv2.IMREAD_GRAYSCALE) # 使用一张低对比度的图像
if img is not None:
# 应用直方图均衡化
equalized_img = cv2.equalizeHist(img)

cv2.imshow('Original', img)
cv2.imshow('Equalized', equalized_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

```

11. 特征检测与描述

特征检测和描述是计算机视觉中的一个重要领域,用于识别图像中的关键点和特征,以便进行图像匹配、对象识别等任务。OpenCV 提供了多种特征检测和描述算法。

  • Harris 角点检测: cv2.cornerHarris()
  • Shi-Tomasi 角点检测: cv2.goodFeaturesToTrack()
  • SIFT (Scale-Invariant Feature Transform): cv2.SIFT_create() (可能需要在 opencv-contrib-python 中)
  • SURF (Speeded-Up Robust Features): cv2.SURF_create() (可能需要在 opencv-contrib-python 中)
  • ORB (Oriented FAST and Rotated BRIEF): cv2.ORB_create()

由于 SIFT 和 SURF 算法可能受专利保护,它们可能不在标准的 OpenCV 安装中。如果需要使用它们,请确保安装了 opencv-contrib-python

下面是一个使用 ORB 特征检测和描述的示例:

```python
import cv2

img1 = cv2.imread('box.png', cv2.IMREAD_GRAYSCALE) # 目标图像
img2 = cv2.imread('box_in_scene.png', cv2.IMREAD_GRAYSCALE) # 场景图像
if img1 is not None and img2 is not None:
# 创建 ORB 对象
orb = cv2.ORB_create()

# 检测关键点并计算描述符
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)

# 创建 BFMatcher (Brute-Force Matcher) 对象
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

# 匹配描述符
matches = bf.match(des1, des2)

# 根据距离排序匹配
matches = sorted(matches, key=lambda x: x.distance)

# 绘制最佳匹配
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv2.imshow("Matches", img3)

cv2.waitKey(0)
cv2.destroyAllWindows()

```

12. 视频处理

OpenCV 不仅可以处理静态图像,还可以处理视频。

12.1 读取视频

cv2.VideoCapture()

```python
import cv2

从文件读取视频

cap = cv2.VideoCapture('video.mp4')

从摄像头读取视频 (0 表示默认摄像头)

cap = cv2.VideoCapture(0)

if not cap.isOpened():
print("Error: Could not open video.")
exit()

while True:
# 读取一帧
ret, frame = cap.read()

# 如果成功读取到帧
if ret:
    # 在此处进行帧处理 (例如,转换为灰度)
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 显示帧
    cv2.imshow('Video', gray_frame)

    # 按 'q' 键退出
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
else:
    break

释放资源

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

12.2 写入视频

cv2.VideoWriter()

```python
import cv2
cap = cv2.VideoCapture('video.mp4')

if not cap.isOpened():
print("Error opening video stream or file")

获取视频的宽度和高度

frame_width = int(cap.get(3))
frame_height = int(cap.get(4))

定义编解码器并创建 VideoWriter 对象

fourcc = cv2.VideoWriter_fourcc(*'XVID') # 或使用其他编解码器
out = cv2.VideoWriter('output.avi', fourcc, 20.0, (frame_width, frame_height))

while cap.isOpened():
ret, frame = cap.read()
if ret:
# 在此处进行帧处理

    # 写入处理后的帧
    out.write(frame)

    cv2.imshow('frame', frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
else:
    break

释放资源

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

13. 对象跟踪
OpenCV提供了几种对象跟踪算法, 下面是一个使用 cv2.TrackerCSRT_create()的例子:
```python
import cv2

读取视频

cap = cv2.VideoCapture("video.mp4")

创建跟踪器

tracker = cv2.TrackerCSRT_create()

读取第一帧

ret, frame = cap.read()

选择要跟踪的对象 (使用鼠标选择一个矩形区域)

bbox = cv2.selectROI("Tracking", frame, False)

初始化跟踪器

tracker.init(frame, bbox)

def drawBox(img,bbox):
x, y, w, h = int(bbox[0]), int(bbox[1]), int(bbox[2]), int(bbox[3])
cv2.rectangle(img, (x, y), ((x + w), (y + h)), (255, 0, 255), 3, 3 )
cv2.putText(img, "Tracking", (100, 75), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)

while True:
timer = cv2.getTickCount()
ret, frame = cap.read()
if not ret:
break;
# 更新跟踪器
success, bbox = tracker.update(frame)

# 绘制跟踪框
if success:
    drawBox(frame,bbox)
else:
    cv2.putText(frame, "Lost", (100, 75), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

# 计算并显示 FPS
fps = cv2.getTickFrequency() / (cv2.getTickCount() - timer)
cv2.putText(frame, str(int(fps)), (100, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.imshow("Tracking", frame)

if cv2.waitKey(1) & 0xFF == ord('q'):
    break

cap.release()
cv2.destroyAllWindows()
```
总结

OpenCV-Python 是一个功能强大且易于使用的图像处理库。本文只是介绍了 OpenCV 的一部分功能,但涵盖了许多常见的图像处理任务。要充分利用 OpenCV 的潜力,建议深入研究 OpenCV 的官方文档和示例,并根据你的具体需求探索更高级的功能。 记住,图像处理是一个实践性很强的领域,最好的学习方法是动手实践!

THE END