OpenCV 教程

OpenCV (Open Source Computer Vision Library) 是一个功能强大的开源库,广泛用于图像和视频处理、计算机视觉任务(如目标检测、图像分割、特征提取等)。以下是 OpenCV 教程,基于 Python,涵盖安装、核心功能、代码示例和实际应用案例,适合初学者和有一定经验的用户。教程将保持简洁清晰,并提供实用代码。


一、安装 OpenCV

1.1 前提条件

  • Python 版本:建议使用 Python 3.6+。
  • 依赖:NumPy 是必需的,Matplotlib 可用于可视化。

1.2 通过 pip 安装

安装 OpenCV 的 Python 绑定(opencv-python):

pip install opencv-python

安装包含额外模块的版本(如 SIFT、SURF):

pip install opencv-contrib-python

1.3 验证安装

import cv2
print(cv2.__version__)  # 输出版本,例如 "4.10.0"

二、OpenCV 核心概念

  • 图像表示:图像在 OpenCV 中是 NumPy 数组,形状为 (height, width, channels),通道通常是 BGR(蓝绿红)。
  • 基本操作:读取、显示、保存图像;颜色空间转换;几何变换;滤波等。
  • 高级功能:边缘检测、特征提取、目标检测、机器学习集成。
  • 视频处理:处理视频流、摄像头输入、帧操作。
  • 接口一致性:OpenCV 函数通常以 cv2.function_name 调用,参数直观。

三、基础操作

3.1 读取、显示和保存图像

import cv2

# 读取图像
img = cv2.imread('image.jpg')  # 替换为你的图像路径

# 检查是否成功加载
if img is None:
    print("Error: Could not load image")
else:
    # 显示图像
    cv2.imshow('Image', img)
    cv2.waitKey(0)  # 按任意键关闭窗口
    cv2.destroyAllWindows()

    # 保存图像
    cv2.imwrite('output.jpg', img)

说明

  • imread:支持多种格式(如 JPG、PNG)。
  • imshow:创建窗口显示图像。
  • waitKey(0):等待用户输入,0 表示无限等待。
  • imwrite:保存图像到指定路径。

3.2 颜色空间转换

OpenCV 默认使用 BGR 格式,需转换为 RGB(用于 Matplotlib)或灰度图。

# 转换为灰度
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 转换为 RGB
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 显示灰度图像
cv2.imshow('Gray Image', gray_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

3.3 图像缩放和裁剪

# 缩放(50% 大小)
resized_img = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_LINEAR)

# 裁剪(指定区域)
cropped_img = img[100:300, 200:400]  # [y_start:y_end, x_start:x_end]

# 保存结果
cv2.imwrite('resized.jpg', resized_img)
cv2.imwrite('cropped.jpg', cropped_img)

四、图像处理

4.1 模糊(平滑)

使用高斯模糊去除噪声:

# 高斯模糊
blurred_img = cv2.GaussianBlur(img, (5, 5), 0)  # 核大小为 5x5
cv2.imwrite('blurred.jpg', blurred_img)

4.2 边缘检测

使用 Canny 边缘检测:

# 转换为灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Canny 边缘检测
edges = cv2.Canny(gray, 100, 200)  # 阈值 100 和 200
cv2.imwrite('edges.jpg', edges)

4.3 阈值分割

将图像二值化:

# 转换为灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 自适应阈值
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
cv2.imwrite('threshold.jpg', thresh)

五、特征检测与匹配

5.1 角点检测

使用 Harris 角点检测:

# 转换为灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)

# Harris 角点检测
corners = cv2.cornerHarris(gray, blockSize=2, ksize=3, k=0.04)

# 标记角点
img[corners > 0.01 * corners.max()] = [0, 0, 255]  # 红点标记
cv2.imwrite('corners.jpg', img)

5.2 SIFT 特征提取与匹配

SIFT(尺度不变特征变换)用于特征点检测和匹配:

# 创建 SIFT 对象
sift = cv2.SIFT_create()

# 检测关键点和描述符
kp1, des1 = sift.detectAndCompute(img, None)

# 绘制关键点
img_with_kp = cv2.drawKeypoints(img, kp1, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imwrite('sift_keypoints.jpg', img_with_kp)

注意:SIFT 在 opencv-contrib-python 中可用,主包中不可用。


六、视频处理

6.1 读取和显示视频

# 打开视频文件
cap = cv2.VideoCapture('video.mp4')  # 替换为你的视频路径

while cap.isOpened():
    ret, frame = cap.read()  # 读取一帧
    if not ret:
        break

    # 显示帧
    cv2.imshow('Video', frame)
    if cv2.waitKey(25) & 0xFF == ord('q'):  # 按 'q' 退出
        break

cap.release()
cv2.destroyAllWindows()

6.2 摄像头实时处理

# 打开摄像头
cap = cv2.VideoCapture(0)  # 0 表示默认摄像头

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break

    # 转换为灰度并显示
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    cv2.imshow('Camera', gray)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

七、与 Scikit-learn 集成

OpenCV 可与 Scikit-learn 结合,用于机器学习任务(如图像分类)。

示例:手写数字分类

使用 MNIST 数据集(需额外下载或用 sklearn 的 load_digits)。

from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
import cv2
import numpy as np

# 加载数据
digits = load_digits()
X, y = digits.data, digits.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 数据预处理(标准化)
X_train = X_train / 16.0  # 归一化到 [0, 1]
X_test = X_test / 16.0

# 训练 SVM
model = SVC(kernel='rbf', random_state=42)
model.fit(X_train, y_train)

# 预测
y_pred = model.predict(X_test)
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")

输出示例

Accuracy: 0.986

说明:OpenCV 可用于预处理图像(如降噪、边缘检测),然后将特征输入 Scikit-learn 模型。


八、应用案例:人脸检测

使用 OpenCV 的预训练 Haar 级联分类器进行人脸检测。

# 加载预训练人脸检测器
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

# 读取图像
img = cv2.imread('face.jpg')  # 替换为包含人脸的图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 检测人脸
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)

# 绘制矩形框
for (x, y, w, h) in faces:
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)

# 保存结果
cv2.imwrite('face_detected.jpg', img)

说明

  • haarcascade_frontalface_default.xml 是 OpenCV 内置的预训练模型。
  • detectMultiScale 返回人脸的坐标和尺寸。

九、注意事项

  1. 图像格式
  • OpenCV 使用 BGR 格式,与 Matplotlib 的 RGB 不同,需转换。
  • 确保图像路径正确,文件存在。
  1. 性能优化
  • 对于大型图像或视频,考虑降低分辨率或使用 GPU 版本(OpenCV-DNN)。
  • 避免在循环中重复加载模型或分类器。
  1. 内存管理
  • 释放视频捕获对象(cap.release())和关闭窗口(cv2.destroyAllWindows())。
  1. 版本兼容性
  • 某些功能(如 SIFT)需 opencv-contrib-python
  • 检查 OpenCV 版本:cv2.__version__
  1. 错误处理
  • 检查 imreadVideoCapture 是否返回 None/False。
  • 确保输入数据格式正确(如 NumPy 数组)。

十、资源

  • 官方文档:https://docs.opencv.org/master/
  • Python 教程:https://opencv-python-tutroals.readthedocs.io/en/latest/
  • 示例代码:https://github.com/opencv/opencv/tree/master/samples/python
  • 社区:在 X 平台搜索 #opencv 获取最新讨论。

十一、完整示例:边缘检测与分类

结合 OpenCV 和 Scikit-learn 进行图像预处理和分类:

from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.pipeline import Pipeline
from sklearn.metrics import accuracy_score
import cv2
import numpy as np

# 加载数据
digits = load_digits()
X, y = digits.data, digits.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 自定义边缘特征提取器
class EdgeFeatureExtractor:
    def fit(self, X, y=None):
        return self

    def transform(self, X):
        features = []
        for img in X:
            img_2d = img.reshape(8, 8).astype(np.uint8)
            edges = cv2.Canny(img_2d, 100, 200)
            features.append(edges.flatten())
        return np.array(features)

# 创建 Pipeline
pipeline = Pipeline([
    ('edge', EdgeFeatureExtractor()),
    ('scaler', StandardScaler()),
    ('classifier', SVC(kernel='rbf', random_state=42))
])

# 训练和预测
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}")

# 保存模型
import joblib
joblib.dump(pipeline, 'digits_edge_model.pkl')

输出示例

Accuracy: 0.953

说明:使用 OpenCV 的 Canny 边缘检测提取特征,再用 Scikit-learn 的 SVM 分类。


如果需要 更具体的 OpenCV 应用(如目标跟踪、图像分割、深度学习集成)、可视化代码(如边缘检测结果展示),或针对特定任务的完整示例,请告诉我,我可以提供更详细的代码或优化方案!

类似文章

发表回复

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