OpenCV Python 基础与高级应用 – wiki大全

OpenCV Python:从基础到高级应用

OpenCV(Open Source Computer Vision Library)是一个功能强大的开源库,专注于计算机视觉、机器学习和图像处理领域。它支持多种编程语言,包括 Python、C++、Java 和 MATLAB。本文将引导您了解 OpenCV 与 Python 的基本概念,然后深入探讨一些高级应用,并提供实用的代码示例。

1. 入门:安装与基本图像操作

在开始之前,请确保您已安装 OpenCV。如果尚未安装,可以使用 pip 进行安装:

bash
pip install opencv-python numpy

NumPy 对于在 Python 中高效处理图像数据至关重要,因为 OpenCV 将图像表示为 NumPy 数组。

1.1 读取、显示和保存图像

最基本的操作包括加载图像、显示图像以及保存任何修改。

“`python
import cv2

读取图像

参数 0 以灰度图模式读取图像

参数 1 以彩色图模式读取图像(默认值)

参数 -1 读取包含 alpha 通道的图像

img = cv2.imread(‘image.jpg’, 1)

if img is None:
print(“错误:无法读取图像。请检查文件路径。”)
else:
# 在窗口中显示图像
cv2.imshow(‘原始图像’, img)

# 无限等待直到按下任意键
cv2.waitKey(0)

# 销毁所有创建的窗口
cv2.destroyAllWindows()

# 保存修改后的图像
cv2.imwrite('new_image.png', img)

“`

1.2 访问像素值和图像属性

图像本质上是像素值的矩阵。对于灰度图像,每个像素有一个强度值 (0-255)。对于彩色图像(OpenCV 中为 BGR 格式),每个像素有三个值(蓝色、绿色、红色)。

“`python
import cv2

img = cv2.imread(‘image.jpg’)

if img is not None:
# 获取图像尺寸(高、宽、通道数)
height, width, channels = img.shape
print(f”图像尺寸: {width}x{height}, 通道数: {channels}”)

# 访问像素值(例如,在第 100 行、第 100 列)
# 对于彩色图像,它返回一个 BGR 数组
pixel = img[100, 100]
print(f"在 (100, 100) 处的像素值: {pixel}")

# 修改像素值(例如,设置为蓝色)
img[100, 100] = [255, 0, 0] # BGR 格式
print(f"在 (100, 100) 处修改后的像素值: {img[100, 100]}")

# 访问单个颜色通道
blue = img[100, 100, 0]
green = img[100, 100, 1]
red = img[100, 100, 2]
print(f"蓝色: {blue}, 绿色: {green}, 红色: {red}")

cv2.imshow('修改后的图像', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

“`

2. 核心图像处理技术

OpenCV 提供了一套丰富的函数用于图像处理。

2.1 灰度转换和阈值处理

转换为灰度图通过减少数据来简化图像处理。阈值处理用于将图像分割为前景和背景。

“`python
import cv2

img = cv2.imread(‘image.jpg’)

if img is not None:
# 转换为灰度图
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow(‘灰度图像’, gray_img)

# 简单阈值处理
# 像素值高于 127 的变为 255(白色),否则变为 0(黑色)
ret, thresh_binary = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY)
cv2.imshow('二值阈值', thresh_binary)

# 自适应阈值处理(适用于光照条件变化的场景)
# 使用小范围邻域确定阈值
thresh_adaptive = cv2.adaptiveThreshold(gray_img, 255,
                                        cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                        cv2.THRESH_BINARY, 11, 2)
cv2.imshow('自适应阈值', thresh_adaptive)

cv2.waitKey(0)
cv2.destroyAllWindows()

“`

2.2 模糊和平滑

模糊有助于降噪和平滑图像。常见的技术包括高斯模糊、中值模糊和双边滤波。

“`python
import cv2

img = cv2.imread(‘image.jpg’)

if img is not None:
# 高斯模糊:在降噪的同时更好地保留边缘
# 核大小 (5,5),X 和 Y 方向的标准差 (0)
gaussian_blur = cv2.GaussianBlur(img, (5, 5), 0)
cv2.imshow(‘高斯模糊’, gaussian_blur)

# 中值模糊:有效去除椒盐噪声
# 核大小 (5)
median_blur = cv2.medianBlur(img, 5)
cv2.imshow('中值模糊', median_blur)

# 双边滤波:在去除噪声的同时高度有效地保留边缘
# 参数:图像、像素邻域直径、sigmaColor、sigmaSpace
bilateral_filter = cv2.bilateralFilter(img, 9, 75, 75)
cv2.imshow('双边滤波', bilateral_filter)

cv2.waitKey(0)
cv2.destroyAllWindows()

“`

2.3 边缘检测 (Canny)

Canny 边缘检测器是一种多阶段算法,用于检测图像中各种边缘。

“`python
import cv2

img = cv2.imread(‘image.jpg’, 0) # 以灰度图模式读取

if img is not None:
# Canny 边缘检测
# 参数:图像、threshold1、threshold2
# 梯度强度高于 threshold2 的边缘是确定的边缘。
# 梯度强度低于 threshold1 的边缘被拒绝。
# 梯度强度介于 threshold1 和 threshold2 之间的边缘,只有当它们与确定边缘连接时才被分类为边缘。
edges = cv2.Canny(img, 100, 200)
cv2.imshow(‘Canny 边缘’, edges)

cv2.waitKey(0)
cv2.destroyAllWindows()

“`

3. 高级应用

OpenCV 的功能远不止基本的图像处理,它还能实现复杂的计算机视觉任务。

3.1 人脸检测 (Haar Cascades)

Haar Cascades 是一种基于机器学习的对象检测算法。OpenCV 提供了预训练的分类器,用于检测各种对象,包括人脸。

“`python
import cv2

加载预训练的人脸级联分类器

face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + ‘haarcascade_frontalface_default.xml’)

加载图像

img = cv2.imread(‘people.jpg’)

if img is None:
print(“错误:无法读取图像。请检查文件路径。”)
else:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 在图像中检测人脸
# scaleFactor: 指定每次图像金字塔缩放的比例。
# minNeighbors: 指定每个候选矩形应该保留多少个邻居。
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))

# 在检测到的人脸周围绘制矩形
for (x, y, w, h) in faces:
    cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2) # 蓝色矩形,厚度 2

cv2.imshow('检测到的人脸', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

``
*注意:请确保您有
haarcascade_frontalface_default.xml` 文件,通常在您的 OpenCV 安装目录中找到或从 OpenCV GitHub 仓库下载。*

3.2 对象跟踪 (MeanShift/CamShift)

对象跟踪涉及在视频序列中跟随移动的对象。MeanShift 和 CamShift 是为此目的设计的算法,通常在初始检测之后使用。

“`python
import cv2
import numpy as np

打开视频捕获

cap = cv2.VideoCapture(‘video.mp4’)

if not cap.isOpened():
print(“错误:无法打开视频。”)
else:
# 获取视频的第一帧
ret, frame = cap.read()

# 设置窗口的初始位置(例如,手动选择一个感兴趣区域)
# 为了演示,我们假设我们知道对象的初始位置
x, y, w, h = 300, 200, 100, 50 # 示例: (x,y,宽度,高度)
track_window = (x, y, w, h)

# 设置用于跟踪的 ROI
roi = frame[y:y+h, x:x+w]
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
# 遮罩低饱和度值以避免噪声
mask = cv2.inRange(hsv_roi, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)

# 设置终止条件,要么 10 次迭代,要么移动至少 1 个像素
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

while(1):
    ret, frame = cap.read()
    if ret == True:
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)

        # 应用 CamShift 获取新位置
        ret, track_window = cv2.CamShift(dst, track_window, term_crit)

        # 在图像上绘制
        pts = cv2.boxPoints(ret)
        pts = np.int0(pts)
        img2 = cv2.polylines(frame, [pts], True, (0, 255, 255), 2) # 黄色矩形
        cv2.imshow('CamShift 跟踪', img2)

        k = cv2.waitKey(30) & 0xff
        if k == 27: # ESC 键退出
            break
    else:
        break

cv2.destroyAllWindows()
cap.release()

``
*注意:对于此示例,您需要一个
video.mp4文件。初始的x, y, w, h` 值应对应于您想在第一帧中跟踪的对象。*

3.3 特征匹配 (SIFT/SURF/ORB)

特征匹配对于对象识别、图像拼接和 3D 重建等任务至关重要。SIFT (尺度不变特征变换)、SURF (加速稳健特征) 和 ORB (Oriented FAST and Rotated BRIEF) 等算法可以检测图像中独特的关键点和描述符。ORB 是 SIFT 和 SURF 专利算法的一个很好的免费替代品。

“`python
import cv2
import matplotlib.pyplot as plt

加载图像

img1 = cv2.imread(‘box.png’, 0) # 查询图像(待检测对象)
img2 = cv2.imread(‘box_in_scene.png’, 0) # 训练图像(场景)

if img1 is None or img2 is None:
print(“错误:无法读取图像。请检查文件路径。”)
else:
# 初始化 ORB 检测器
orb = cv2.ORB_create()

# 使用 ORB 查找关键点和描述符
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)

# 创建 BFMatcher 对象(暴力匹配器)
# 它接受两个可选参数:normType 和 crossCheck
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

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

# 按照距离排序(最佳匹配在前)
matches = sorted(matches, key = lambda x:x.distance)

# 绘制前 10 个匹配项
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)

plt.imshow(img3), plt.show()

``
*注意:您需要
box.pngbox_in_scene.png` 图像才能运行此示例。这些图像应包含一个共同对象,以便特征匹配有效。*

结论

OpenCV 与 Python 结合,为各种计算机视觉任务提供了一个极其多功能的工具包。从读取、显示和过滤等基本图像操作,到人脸检测、对象跟踪和特征匹配等高级应用,其功能都非常广泛。本文仅触及了表面,但它为探索更复杂的主题(如深度学习集成、增强现实和 3D 视觉)提供了坚实的基础。深入研究时,请记住查阅 OpenCV 官方文档,以获取其功能和参数的全面详细信息。

滚动至顶部