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返回人脸的坐标和尺寸。
九、注意事项
- 图像格式:
- OpenCV 使用 BGR 格式,与 Matplotlib 的 RGB 不同,需转换。
- 确保图像路径正确,文件存在。
- 性能优化:
- 对于大型图像或视频,考虑降低分辨率或使用 GPU 版本(OpenCV-DNN)。
- 避免在循环中重复加载模型或分类器。
- 内存管理:
- 释放视频捕获对象(
cap.release())和关闭窗口(cv2.destroyAllWindows())。
- 版本兼容性:
- 某些功能(如 SIFT)需
opencv-contrib-python。 - 检查 OpenCV 版本:
cv2.__version__。
- 错误处理:
- 检查
imread或VideoCapture是否返回 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 应用(如目标跟踪、图像分割、深度学习集成)、可视化代码(如边缘检测结果展示),或针对特定任务的完整示例,请告诉我,我可以提供更详细的代码或优化方案!