前言
OpenCV(Open Source Computer Vision Library)是一个广泛使用的开源计算机视觉库,旨在为实时图像处理提供高效的计算工具。它提供了数百种算法和函数,用于处理图像和视频。OpenCV 在工业、学术研究和个人项目中应用广泛,适用于各种任务,如对象检测、图像增强、计算机视觉中的机器学习等。
在本教程中,我们将详细介绍 OpenCV 的常用功能,包括图像处理、视频处理以及如何结合其他机器学习框架(如 TensorFlow 和 PyTorch)进行应用。
目录
-
OpenCV 基础
- 安装 OpenCV
- 读取与显示图像
- 保存图像与视频
- 调整图像尺寸与裁剪
-
图像处理
- 图像颜色空间转换
- 图像平滑与滤波
- 边缘检测与轮廓检测
- 图像几何变换
-
对象检测与跟踪
- 使用 Haar 级联分类器进行人脸检测
- 使用深度学习模型进行对象检测
- 视频跟踪与运动检测
-
高级功能
- OpenCV 与机器学习(TensorFlow、PyTorch)
- 使用 OpenCV 进行相机校准与立体视觉
- 图像分割与图像形态学操作
1. OpenCV 基础
安装 OpenCV
你可以使用 pip 安装 OpenCV:
pip install opencv-python
安装带有 contrib 模块 的 OpenCV:
pip install opencv-contrib-python
导入 OpenCV:
import cv2
读取与显示图像
OpenCV 提供了简单的函数来读取和显示图像:
- 读取图像:
# 读取一张图像
image = cv2.imread('image.jpg')
# 打印图像的形状(高度、宽度、通道)
print(image.shape)
- 显示图像:
# 显示图像
cv2.imshow('Image', image)
# 等待按键输入,然后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
保存图像与视频
- 保存图像:
# 保存图像
cv2.imwrite('output.jpg', image)
- 保存视频:
# 定义视频编解码器并创建 VideoWriter 对象
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
# 写入视频帧
out.write(image) # 假设 image 是一个视频帧
out.release() # 释放 VideoWriter
调整图像尺寸与裁剪
- 调整图像尺寸:
# 调整图像大小为 300x300
resized_image = cv2.resize(image, (300, 300))
- 裁剪图像:
# 裁剪图像的区域
cropped_image = image[50:200, 100:300] # 从 (50, 100) 到 (200, 300) 的区域
2. 图像处理
图像颜色空间转换
OpenCV 支持多种颜色空间,如 BGR、RGB、HSV、灰度等。你可以轻松转换图像的颜色空间:
- BGR 转换为灰度图像:
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
- BGR 转换为 HSV:
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
边缘检测与轮廓检测
OpenCV 提供了 Canny 边缘检测 和 轮廓检测 来识别图像中的对象轮廓。
- Canny 边缘检测:
edges = cv2.Canny(image, 100, 200)
cv2.imshow('Edges', edges)
cv2.waitKey(0)
- 查找轮廓:
# 转换为灰度图像并进行二值化
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)
# 查找轮廓
contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv2.drawContours(image, contours, -1, (0, 255, 0), 2)
cv2.imshow('Contours', image)
cv2.waitKey(0)
图像几何变换
你可以对图像进行几何变换,如旋转、平移、缩放等。
- 图像旋转:
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
# 旋转图像 45 度
matrix = cv2.getRotationMatrix2D(center, 45, 1.0)
rotated_image = cv2.warpAffine(image, matrix, (w, h))
- 图像平移:
# 定义平移矩阵,将图像向右移动 50 像素,向下移动 100 像素
M = np.float32([[1, 0, 50], [0, 1, 100]])
shifted_image = cv2.warpAffine(image, M, (w, h))
3. 对象检测与跟踪
使用 Haar 级联分类器进行人脸检测
OpenCV 提供了 Haar 级联分类器,适用于快速检测人脸或其他对象。
- 加载预训练的 Haar 分类器:
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
# 转换为灰度图像
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 检测人脸
faces = face_cascade.detectMultiScale(gray_image, scaleFactor=1.1, minNeighbors=5)
# 绘制检测到的人脸
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x+w, y+h), (255, 0, 0), 2)
cv2.imshow('Faces', image)
cv2.waitKey(0)
使用深度学习模型进行对象检测
OpenCV 支持加载深度学习模型进行对象检测,如 YOLO、SSD 等。
- 加载 YOLO 模型:
# 加载 YOLO 模型的配置和权重
net = cv2.dnn.readNet('yolov3.weights', 'yolov3.cfg')
# 加载对象类别名称
with open('coco.names', 'r') as f:
classes = f.read().splitlines()
# 读取输入图像并进行预处理
blob = cv2.dnn.blobFromImage(image, 1/255.0, (416, 416), swapRB=True, crop=False)
net.setInput(blob)
# 获取 YOLO 输出
layer_names = net.getLayerNames()
output_layers = [layer_names[i - 1] for i in net.getUnconnectedOutLayers()]
detections = net.forward(output_layers)
# 解析并显示检测结果
for detection in detections:
for obj in detection:
confidence = obj[4]
if confidence > 0.5:
# 显示检测到的对象
print("Detected object with confidence:", confidence)
视频跟踪与运动检测
OpenCV 提供了多种视频跟踪算法,如 CSRT、KCF,并可以检测运动。
- 使用 CSRT 进行视频跟踪:
tracker = cv2.TrackerCSRT_create()
# 初始化视频流
cap = cv2.VideoCapture('video.mp4')
# 选择目标
ret, frame = cap.read()
bbox = cv2.selectROI('Tracking', frame, fromCenter=False)
tracker.init(frame, bbox)
while True:
ret, frame = cap.read()
if not ret:
break
# 更新跟踪器
success, bbox = tracker.update(frame)
# 如果跟踪成功,绘制边界框
if success:
x, y, w, h = map(int, bbox)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(frame, 'Tracking', (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
else:
cv2.putText(frame, 'Lost', (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
# 显示视频帧
cv2.imshow('Tracking', frame)
# 退出条件:按下 "q" 键
if cv2.waitKey(30) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
- 运动检测(背景减法):
背景减法 是运动检测中常用的技术。OpenCV 提供了 cv2.createBackgroundSubtractorMOG2()
和 cv2.createBackgroundSubtractorKNN()
两种方法来检测运动区域。
# 创建背景减法器
bg_subtractor = cv2.createBackgroundSubtractorMOG2()
# 打开视频流
cap = cv2.VideoCapture('video.mp4')
while True:
ret, frame = cap.read()
if not ret:
break
# 应用背景减法
fg_mask = bg_subtractor.apply(frame)
# 显示前景掩膜
cv2.imshow('Foreground Mask', fg_mask)
# 退出条件:按下 "q" 键
if cv2.waitKey(30) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
通过背景减法器,我们可以检测视频中的运动物体,适合用于安防监控或物体跟踪等任务。
4. 高级功能
OpenCV 与机器学习(TensorFlow、PyTorch)
OpenCV 可以与深度学习框架如 TensorFlow 和 PyTorch 结合使用,实现计算机视觉中的高级任务。你可以使用这些框架来构建深度学习模型,然后使用 OpenCV 进行推理和处理图像。
- 使用 TensorFlow 进行图像分类:
假设我们已经训练了一个图像分类模型,可以通过 TensorFlow 加载该模型,并使用 OpenCV 处理输入图像。
import tensorflow as tf
import cv2
# 加载 TensorFlow 模型
model = tf.keras.models.load_model('my_model.h5')
# 读取并预处理图像
image = cv2.imread('image.jpg')
resized_image = cv2.resize(image, (224, 224)) # 假设模型输入尺寸为 224x224
input_image = resized_image / 255.0 # 归一化处理
input_image = input_image.reshape(1, 224, 224, 3) # 增加批次维度
# 进行预测
predictions = model.predict(input_image)
print('Predictions:', predictions)
- 使用 PyTorch 进行对象检测:
你也可以使用 PyTorch 构建深度学习模型,并将 OpenCV 作为图像预处理和后处理工具。
import torch
import torchvision.transforms as transforms
from PIL import Image
# 加载 PyTorch 模型
model = torch.load('my_model.pth')
model.eval()
# 使用 OpenCV 读取图像并转换为 PIL 图像
image = cv2.imread('image.jpg')
image_pil = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
# 定义图像转换
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
# 应用转换
input_tensor = transform(image_pil).unsqueeze(0) # 增加批次维度
# 进行预测
with torch.no_grad():
predictions = model(input_tensor)
print('Predictions:', predictions)
使用 OpenCV 进行相机校准与立体视觉
相机校准 是计算机视觉中的一个常见任务,目的是校正相机的光学失真。OpenCV 提供了方便的工具来实现相机校准。
- 相机校准:
假设你有一组棋盘图像,可以通过这些图像进行相机校准。
import numpy as np
import cv2
# 设置棋盘角点的尺寸
chessboard_size = (9, 6)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# 准备世界坐标系的棋盘点
objp = np.zeros((chessboard_size[0] * chessboard_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2)
# 用于存储对象点和图像点
objpoints = [] # 3D 点
imgpoints = [] # 2D 点
# 读取棋盘图像
images = ['chessboard1.jpg', 'chessboard2.jpg'] # 替换为实际图像路径
for image_path in images:
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 查找棋盘角点
ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)
if ret:
objpoints.append(objp)
# 提高角点的准确性
corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
imgpoints.append(corners2)
# 显示角点
cv2.drawChessboardCorners(img, chessboard_size, corners2, ret)
cv2.imshow('Chessboard Corners', img)
cv2.waitKey(500)
# 进行相机校准
ret, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
print('Camera Matrix:', camera_matrix)
print('Distortion Coefficients:', dist_coeffs)
cv2.destroyAllWindows()
通过相机校准,你可以获得相机的内参(如焦距、主点位置)和畸变系数,从而校正拍摄的图像。
- 立体视觉与深度图:
你还可以使用 OpenCV 实现立体视觉,通过两台相机捕捉的图像计算深度信息。
# 假设你已经捕获了左图和右图
imgL = cv2.imread('left_image.jpg', 0)
imgR = cv2.imread('right_image.jpg', 0)
# 创建 SGBM 立体匹配对象
stereo = cv2.StereoSGBM_create(minDisparity=0, numDisparities=16, blockSize=15)
# 计算视差图
disparity = stereo.compute(imgL, imgR)
# 显示视差图
cv2.imshow('Disparity', disparity)
cv2.waitKey(0)
cv2.destroyAllWindows()
视差图可以反映图像中各个像素的深度信息,常用于 3D 建模和场景重建。
图像分割与图像形态学操作
图像分割 是将图像划分为不同区域或对象的过程。图像形态学操作 可以用于提取对象的形状特征。
- 分水岭算法进行图像分割:
# 转换为灰度图并进行二值化
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# 应用形态学操作
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel, iterations=2)
# 确定背景区域
sure_bg = cv2.dilate(opening, kernel, iterations=3)
# 寻找前景区域
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
# 确定未知区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)
# 标记连接的组件
ret, markers = cv2.connectedComponents(sure_fg)
# 增加1,确保背景为 1,前景为其他值
markers = markers + 1
# 将未知区域标记为 0
markers[unknown == 255] = 0
# 应用分水岭算法
markers = cv2.watershed(image, markers)
# 将边界标记为红色
image[markers == -1] = [0, 0, 255]
cv2.imshow('Watershed Segmentation', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
结论
通过本详细的 OpenCV 教程,你已经学习了从基本的图像与视频处理到高级的对象检测、分割和形态学操作。你掌握了如何读取、保存和显示图像,并通过颜色空间转换、滤波、边缘检测等图像处理技术对图像进行分析。同时,我们还讨论了如何利用 OpenCV 进行对象跟踪和运动检测,以及如何结合 TensorFlow 和 PyTorch 等深度学习框架进行高级计算机视觉任务。