【OpenCV Python入门指南】:从零开始轻松驾驭计算机视觉
发布时间: 2024-08-05 15:10:08 阅读量: 38 订阅数: 44
计算机视觉+OpenCV+Python教程+入门指南
![【OpenCV Python入门指南】:从零开始轻松驾驭计算机视觉](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9BbWpHYmZkT055bjQwaHZvUHIzS2V2bVZHTkp2WVdwaGtqZmtJbjlpYU5QYVpRdE5GN3FIOWhPc3JKenUwc1VkUTBZUHFRQ1NBUnE3aWJpY3RJQ0tNc0czZy82NDA?x-oss-process=image/format,png)
# 1. OpenCV Python基础
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,提供了一系列图像处理和计算机视觉算法。本章将介绍OpenCV Python基础,包括图像读写、显示、几何变换和色彩空间转换。
### 1.1 图像读写与显示
**图像读写操作**
```python
import cv2
# 读取图像
image = cv2.imread('image.jpg')
# 保存图像
cv2.imwrite('output_image.jpg', image)
```
**图像显示与窗口控制**
```python
# 显示图像
cv2.imshow('Image', image)
cv2.waitKey(0) # 等待按键按下
cv2.destroyAllWindows() # 关闭所有窗口
```
# 2. 图像处理和变换
图像处理和变换是计算机视觉中至关重要的基础操作,它可以增强图像的可视性、提取特征信息、并为后续的图像分析任务做好准备。本章节将介绍 OpenCV 中常用的图像处理和变换操作,包括图像读写、显示、几何变换、色彩空间转换等。
### 2.1 图像读写与显示
#### 2.1.1 图像读写操作
在 OpenCV 中,使用 `cv2.imread()` 函数读取图像,该函数接受图像文件路径作为参数,并返回一个 NumPy 数组,其中包含图像像素值。图像的像素值通常是一个三维数组,其中每个元素表示一个像素的三个颜色通道(红色、绿色、蓝色)。
```python
import cv2
# 读取图像
image = cv2.imread('image.jpg')
# 显示图像
cv2.imshow('Image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
#### 2.1.2 图像显示与窗口控制
读取图像后,可以使用 `cv2.imshow()` 函数显示图像。该函数接受图像和窗口名称作为参数,并在指定的窗口中显示图像。`cv2.waitKey()` 函数用于等待用户输入,按任意键退出窗口。`cv2.destroyAllWindows()` 函数用于关闭所有 OpenCV 窗口。
### 2.2 图像几何变换
#### 2.2.1 图像缩放与旋转
图像缩放和旋转是常见的几何变换,它们可以改变图像的大小和方向。使用 `cv2.resize()` 函数缩放图像,该函数接受图像、目标尺寸和插值方法作为参数。使用 `cv2.rotate()` 函数旋转图像,该函数接受图像、旋转角度和旋转中心作为参数。
```python
# 缩放图像
scaled_image = cv2.resize(image, (500, 500))
# 旋转图像
rotated_image = cv2.rotate(image, cv2.ROTATE_90_CLOCKWISE)
```
#### 2.2.2 图像透视变换
透视变换是一种更复杂的几何变换,它可以将图像从一个视角投影到另一个视角。使用 `cv2.getPerspectiveTransform()` 函数计算透视变换矩阵,然后使用 `cv2.warpPerspective()` 函数应用变换。
```python
# 定义透视变换矩阵
pts1 = np.float32([[0, 0], [500, 0], [0, 500], [500, 500]])
pts2 = np.float32([[100, 100], [400, 100], [100, 400], [400, 400]])
M = cv2.getPerspectiveTransform(pts1, pts2)
# 应用透视变换
transformed_image = cv2.warpPerspective(image, M, (500, 500))
```
### 2.3 图像色彩空间转换
#### 2.3.1 RGB与灰度空间转换
RGB(红色、绿色、蓝色)是图像中最常用的色彩空间,而灰度空间只包含一个通道,表示图像的亮度。使用 `cv2.cvtColor()` 函数在 RGB 和灰度空间之间转换图像。
```python
# 转换为灰度图像
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
```
#### 2.3.2 HSV与LAB空间转换
HSV(色调、饱和度、亮度)和 LAB(亮度、a色、b色)是其他常用的色彩空间,它们可以提供不同的图像表示。使用 `cv2.cvtColor()` 函数在 HSV 和 LAB 空间之间转换图像。
```python
# 转换为 HSV 图像
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# 转换为 LAB 图像
lab_image = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)
```
# 3.1 边缘检测
边缘检测是图像处理中一项基本任务,用于提取图像中物体的轮廓和边界。边缘是图像中像素亮度发生剧烈变化的区域,通常代表物体表面的边界或纹理变化。
#### 3.1.1 Canny边缘检测
Canny边缘检测算法是一种广泛使用的边缘检测方法,它通过以下步骤进行:
1. **高斯滤波:**使用高斯滤波器平滑图像,以去除噪声和保留图像的边缘信息。
2. **计算梯度:**使用Sobel算子计算图像中每个像素的梯度幅度和方向。
3. **非极大值抑制:**在每个像素的梯度方向上,只保留梯度幅度最大的像素。
4. **双阈值化:**使用两个阈值(高阈值和低阈值)对非极大值抑制后的图像进行阈值化。高阈值用于确定强边缘,而低阈值用于确定弱边缘。
5. **滞后阈值化:**使用滞后阈值化技术连接弱边缘和强边缘,以生成最终的边缘图。
```python
import cv2
import numpy as np
# 读取图像
image = cv2.imread('image.jpg')
# 高斯滤波
blurred_image = cv2.GaussianBlur(image, (5, 5), 0)
# 计算梯度
sobelx = cv2.Sobel(blurred_image, cv2.CV_64F, 1, 0, ksize=5)
sobely = cv2.Sobel(blurred_image, cv2.CV_64F, 0, 1, ksize=5)
# 计算梯度幅度和方向
gradient_magnitude = np.sqrt(sobelx**2 + sobely**2)
gradient_direction = np.arctan2(sobely, sobelx)
# 非极大值抑制
non_max_suppressed = np.zeros_like(gradient_magnitude)
for i in range(1, gradient_magnitude.shape[0]-1):
for j in range(1, gradient_magnitude.shape[1]-1):
if gradient_magnitude[i, j] == np.max(gradient_magnitude[i-1:i+2, j-1:j+2]):
non_max_suppressed[i, j] = gradient_magnitude[i, j]
# 双阈值化
high_threshold = 0.1 * np.max(non_max_suppressed)
low_threshold = 0.05 * np.max(non_max_suppressed)
edges = np.zeros_like(non_max_suppressed)
edges[non_max_suppressed >= high_threshold] = 255
edges[np.logical_and(non_max_suppressed >= low_threshold, non_max_suppressed < high_threshold)] = 128
# 滞后阈值化
def hysteresis_thresholding(edges, low_threshold, high_threshold):
weak_edges = np.zeros_like(edges)
strong_edges = np.zeros_like(edges)
weak_edges[edges == 128] = 255
strong_edges[edges == 255] = 255
while True:
new_weak_edges = np.zeros_like(weak_edges)
for i in range(1, weak_edges.shape[0]-1):
for j in range(1, weak_edges.shape[1]-1):
if weak_edges[i, j] == 255 and np.max(strong_edges[i-1:i+2, j-1:j+2]) == 255:
new_weak_edges[i, j] = 255
if np.array_equal(new_weak_edges, weak_edges):
break
weak_edges = new_weak_edges
edges[weak_edges == 255] = 255
return edges
edges = hysteresis_thresholding(edges, low_threshold, high_threshold)
# 显示边缘图
cv2.imshow('Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
#### 3.1.2 Sobel边缘检测
Sobel边缘检测算法是一种更简单的边缘检测方法,它使用以下步骤进行:
1. **高斯滤波:**使用高斯滤波器平滑图像,以去除噪声和保留图像的边缘信息。
2. **计算梯度:**使用Sobel算子计算图像中每个像素的梯度幅度和方向。
3. **阈值化:**使用阈值化技术将梯度幅度图像二值化,以生成最终的边缘图。
```python
import cv2
import numpy as np
# 读取图像
image = cv2.imread('image.jpg')
# 高斯滤波
blurred_image = cv2.GaussianBlur(image, (5, 5), 0)
# 计算梯度
sobelx = cv2.Sobel(blurred_image, cv2.CV_64F, 1, 0, ksize=5)
sobely = cv2.Sobel(blurred_image, cv2.CV_64F, 0, 1, ksize=5)
# 计算梯度幅度和方向
gradient_magnitude = np.sqrt(sobelx**2 + sobely**2)
gradient_direction = np.arctan2(sobely, sobelx)
# 阈值化
threshold = 0.1 * np.max(gradient_magnitude)
edges = np.zeros_like(gradient_magnitude)
edges[gradient_magnitude >= threshold] = 255
# 显示边缘图
cv2.imshow('Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
# 4. 目标检测与跟踪
### 4.1 目标检测
#### 4.1.1 Haar级联分类器
Haar级联分类器是一种基于机器学习的物体检测算法,它使用一组称为Haar特征的简单矩形特征来识别图像中的对象。
**算法原理:**
1. **特征提取:**从图像中提取Haar特征,这些特征是矩形区域的像素和差。
2. **特征选择:**使用AdaBoost算法选择最能区分目标和背景的特征。
3. **级联分类器:**将选定的特征组合成一个级联分类器,其中每个阶段都使用不同的特征集。
**优点:**
* 实时处理速度快
* 训练简单
**缺点:**
* 对目标大小和位置敏感
* 容易受到光照和背景变化的影响
**代码示例:**
```python
import cv2
# 加载Haar级联分类器
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# 读取图像
image = cv2.imread('image.jpg')
# 转换图像为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 检测人脸
faces = face_cascade.detectMultiScale(gray, 1.1, 4)
# 在图像中绘制人脸边界框
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
# 显示图像
cv2.imshow('Detected Faces', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
**逻辑分析:**
* `face_cascade.detectMultiScale()`函数使用Haar级联分类器检测图像中的人脸。
* `1.1`和`4`参数分别指定了缩放因子和最小邻居数。
* `for`循环遍历检测到的人脸,并使用`cv2.rectangle()`函数在图像中绘制边界框。
#### 4.1.2 YOLO目标检测
YOLO(You Only Look Once)是一种单次卷积神经网络(CNN)目标检测算法,它将图像划分为网格,并为每个网格预测对象及其置信度。
**算法原理:**
1. **图像分割:**将图像划分为网格,每个网格负责检测一个对象。
2. **特征提取:**使用CNN从每个网格中提取特征。
3. **边界框预测:**为每个网格预测多个边界框及其置信度。
4. **非极大值抑制:**去除重叠的边界框,只保留置信度最高的边界框。
**优点:**
* 实时处理速度非常快
* 可以检测多个对象
**缺点:**
* 精度可能低于其他目标检测算法
* 对小目标检测效果不佳
**代码示例:**
```python
import cv2
import numpy as np
# 加载YOLO模型
net = cv2.dnn.readNetFromDarknet('yolov3.cfg', 'yolov3.weights')
# 读取图像
image = cv2.imread('image.jpg')
# 将图像预处理为YOLO模型的输入
blob = cv2.dnn.blobFromImage(image, 1/255.0, (416, 416), (0, 0, 0), swapRB=True, crop=False)
# 设置网络输入
net.setInput(blob)
# 前向传播
detections = net.forward()
# 解析检测结果
for detection in detections[0, 0]:
confidence = detection[2]
if confidence > 0.5:
x, y, w, h = detection[3:7] * np.array([image.shape[1], image.shape[0], image.shape[1], image.shape[0]])
cv2.rectangle(image, (int(x-w/2), int(y-h/2)), (int(x+w/2), int(y+h/2)), (0, 255, 0), 2)
# 显示图像
cv2.imshow('Detected Objects', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
**逻辑分析:**
* `cv2.dnn.readNetFromDarknet()`函数加载YOLO模型。
* `cv2.dnn.blobFromImage()`函数将图像预处理为YOLO模型的输入。
* `net.setInput()`函数设置网络输入。
* `net.forward()`函数执行前向传播。
* `for`循环遍历检测到的对象,并使用`cv2.rectangle()`函数在图像中绘制边界框。
# 5.1 图像分割
### 5.1.1 K-Means聚类
K-Means聚类是一种无监督学习算法,用于将数据点聚类到K个簇中。在图像分割中,K-Means聚类可以将图像像素聚类到不同的区域,从而实现图像分割。
**算法流程:**
1. **初始化:**随机选择K个像素作为聚类中心。
2. **分配:**将每个像素分配到距离其最近的聚类中心所在的簇中。
3. **更新:**重新计算每个簇的中心为该簇中所有像素的平均值。
4. **重复:**重复步骤2和3,直到聚类中心不再变化或达到最大迭代次数。
**代码示例:**
```python
import cv2
import numpy as np
# 读入图像
image = cv2.imread('image.jpg')
# 转换为浮点型
image = image.astype(np.float32)
# K-Means聚类
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 3
ret, label, center = cv2.kmeans(image, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
# 将标签转换为uint8类型
label = label.astype(np.uint8)
# 显示分割结果
segmented_image = label.reshape((image.shape[0], image.shape[1]))
cv2.imshow('Segmented Image', segmented_image)
cv2.waitKey(0)
```
### 5.1.2 图像分水岭算法
图像分水岭算法是一种基于区域生长的图像分割算法。它将图像视为一个地形,其中像素强度值表示高度。算法从种子点开始,并向外扩展,将像素分配到不同的区域,直到达到分水岭或边界。
**算法流程:**
1. **初始化:**标记种子点并创建优先队列。
2. **生长:**从优先队列中取出像素,并将其分配到其邻域中强度最小的区域。
3. **更新:**更新优先队列,并继续生长,直到所有像素都被分配。
4. **分水岭:**找到不同区域之间的分水岭,并将其标记为边界。
**代码示例:**
```python
import cv2
# 读入图像
image = cv2.imread('image.jpg')
# 转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 分水岭算法
markers = np.zeros(gray.shape, dtype=np.int32)
markers[50, 50] = 1
markers[100, 100] = 2
cv2.watershed(gray, markers)
# 显示分割结果
segmented_image = np.uint8(markers)
segmented_image[segmented_image == -1] = 0
cv2.imshow('Segmented Image', segmented_image)
cv2.waitKey(0)
```
0
0