OpenCV简介

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,提供了数百个图像处理和计算机视觉算法。

为什么学习OpenCV?

  • 功能强大:涵盖图像处理、目标检测、人脸识别等
  • 性能优异:C++底层实现,速度快
  • 跨平台:支持Windows、Linux、macOS、Android、iOS
  • 多语言:Python、Java、C++等接口

环境安装

Python环境

1
2
3
4
5
6
# 安装OpenCV
pip install opencv-python
pip install opencv-contrib-python # 扩展模块

# 验证安装
python -c "import cv2; print(cv2.__version__)"

基础依赖

1
pip install numpy matplotlib

读取和显示图像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图像
img = cv2.imread('image.jpg')

# 显示图像
cv2.imshow('Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

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

BGR与RGB转换

OpenCV默认使用BGR格式:

1
2
3
4
5
6
7
# BGR转RGB(用于matplotlib显示)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

plt.imshow(img_rgb)
plt.title('Image')
plt.axis('off')
plt.show()

基础图像操作

图像属性

1
2
3
4
5
6
7
8
9
print(f"形状: {img.shape}")     # (height, width, channels)
print(f"大小: {img.size}") # 总像素数
print(f"数据类型: {img.dtype}") # uint8

# 分离通道
b, g, r = cv2.split(img)

# 合并通道
img_merged = cv2.merge([b, g, r])

调整大小

1
2
3
4
5
# 指定尺寸
resized = cv2.resize(img, (800, 600))

# 按比例缩放
resized = cv2.resize(img, None, fx=0.5, fy=0.5)

旋转与翻转

1
2
3
4
5
6
7
8
9
10
# 旋转
height, width = img.shape[:2]
center = (width // 2, height // 2)
M = cv2.getRotationMatrix2D(center, 45, 1.0) # 45度旋转
rotated = cv2.warpAffine(img, M, (width, height))

# 翻转
flipped_h = cv2.flip(img, 1) # 水平翻转
flipped_v = cv2.flip(img, 0) # 垂直翻转
flipped_both = cv2.flip(img, -1) # 同时翻转

裁剪

1
2
# 直接切片
cropped = img[100:300, 150:400] # [y1:y2, x1:x2]

颜色空间转换

1
2
3
4
5
6
7
8
# 灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# LAB
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)

图像滤波

模糊处理

1
2
3
4
5
6
7
8
9
10
11
# 均值滤波
blur = cv2.blur(img, (5, 5))

# 高斯模糊
gaussian = cv2.GaussianBlur(img, (5, 5), 0)

# 中值滤波(去椒盐噪声)
median = cv2.medianBlur(img, 5)

# 双边滤波(保边)
bilateral = cv2.bilateralFilter(img, 9, 75, 75)

边缘检测

1
2
3
4
5
6
# Sobel算子
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=5) # x方向
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=5) # y方向

# Canny边缘检测
edges = cv2.Canny(gray, 50, 150)

阈值处理

1
2
3
4
5
6
7
8
9
10
11
12
13
# 全局阈值
ret, thresh1 = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# 自适应阈值
thresh2 = cv2.adaptiveThreshold(
gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2
)

# Otsu二值化
ret, thresh3 = cv2.threshold(
gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU
)

形态学操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 定义结构元素
kernel = np.ones((5, 5), np.uint8)

# 腐蚀
erosion = cv2.erode(thresh, kernel, iterations=1)

# 膨胀
dilation = cv2.dilate(thresh, kernel, iterations=1)

# 开运算(先腐蚀后膨胀,去噪点)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

# 闭运算(先膨胀后腐蚀,填充空洞)
closing = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

轮廓检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 查找轮廓
contours, hierarchy = cv2.findContours(
thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE
)

# 绘制轮廓
img_contours = img.copy()
cv2.drawContours(img_contours, contours, -1, (0, 255, 0), 2)

# 轮廓属性
for cnt in contours:
# 面积
area = cv2.contourArea(cnt)
# 周长
perimeter = cv2.arcLength(cnt, True)
# 外接矩形
x, y, w, h = cv2.boundingRect(cnt)
# 最小外接圆
(x, y), radius = cv2.minEnclosingCircle(cnt)
# 拟合椭圆
if len(cnt) >= 5:
ellipse = cv2.fitEllipse(cnt)

特征检测

Harris角点

1
2
3
gray = np.float32(gray)
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
img[dst > 0.01 * dst.max()] = [0, 0, 255]

SIFT特征

1
2
3
4
5
6
7
sift = cv2.SIFT_create()
keypoints, descriptors = sift.detectAndCompute(gray, None)

img_kp = cv2.drawKeypoints(
img, keypoints, None,
flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
)

ORB特征(更快)

1
2
3
orb = cv2.ORB_create()
kp, des = orb.detectAndCompute(gray, None)
img_kp = cv2.drawKeypoints(img, kp, None, color=(0, 255, 0))

模板匹配

1
2
3
4
5
6
7
8
template = cv2.imread('template.jpg', 0)
result = cv2.matchTemplate(gray, template, cv2.TM_CCOEFF_NORMED)

threshold = 0.8
loc = np.where(result >= threshold)

for pt in zip(*loc[::-1]):
cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0, 255, 0), 2)

颜色检测

1
2
3
4
5
6
7
8
9
10
11
12
# 转到HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 定义红色范围
lower_red = np.array([0, 50, 50])
upper_red = np.array([10, 255, 255])

# 创建掩码
mask = cv2.inRange(hsv, lower_red, upper_red)

# 应用掩码
result = cv2.bitwise_and(img, img, mask=mask)

实战:人脸检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 加载级联分类器
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, 1.3, 5)

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

cv2.imshow('Faces', img)
cv2.waitKey(0)

实战:车道线检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
def detect_lane(image):
# 灰度化
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 高斯模糊
blur = cv2.GaussianBlur(gray, (5, 5), 0)

# Canny边缘检测
edges = cv2.Canny(blur, 50, 150)

# 定义感兴趣区域
height, width = edges.shape
mask = np.zeros_like(edges)
polygon = np.array([[
(0, height),
(width, height),
(width // 2, height // 2)
]], np.int32)
cv2.fillPoly(mask, polygon, 255)
masked_edges = cv2.bitwise_and(edges, mask)

# 霍夫变换检测直线
lines = cv2.HoughLinesP(
masked_edges, 1, np.pi/180, 50,
minLineLength=50, maxLineGap=150
)

# 绘制车道线
line_image = np.zeros_like(image)
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(line_image, (x1, y1), (x2, y2), (0, 255, 0), 5)

return cv2.addWeighted(image, 0.8, line_image, 1, 0)

视频处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 打开摄像头
cap = cv2.VideoCapture(0)

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

# 处理帧
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

cv2.imshow('Video', gray)

if cv2.waitKey(1) & 0xFF == ord('q'):
break

cap.release()
cv2.destroyAllWindows()

性能优化技巧

  1. 使用NumPy向量化操作
  2. 减小图像尺寸
  3. 使用GPU加速(cv2.cuda模块)
  4. 选择合适的算法(如ORB代替SIFT)

总结

OpenCV功能强大,本文只是冰山一角。建议:

  • 多动手实践
  • 阅读官方文档
  • 参考开源项目

参考资源: