Python 计算机视觉:OpenCV 基础与进阶实践
计算机视觉(Computer Vision, CV)是一门研究如何使计算机“看”和“理解”图像与视频的科学。它在自动驾驶、医学影像分析、工业质检、安防监控、人机交互等领域发挥着举足轻重的作用。在众多计算机视觉库中,OpenCV(Open Source Computer Vision Library)以其功能强大、高效且开源的特性,成为开发者首选的工具。结合 Python 语言的简洁与灵活性,OpenCV 能够让复杂的视觉任务变得触手可及。
本文将从 OpenCV 的基础操作入手,逐步深入到其进阶实践,帮助读者全面掌握使用 Python 进行计算机视觉开发的要点。
一、OpenCV 基础:入门与图像操作
1. 安装 OpenCV
在 Python 中安装 OpenCV 非常简单,只需使用 pip 命令:
bash
pip install opencv-python numpy
numpy 是 OpenCV 图像数据处理的基础,因此通常会一同安装。
2. 图像的读取、显示与保存
OpenCV 将图像视为多维 NumPy 数组。
“`python
import cv2
import numpy as np
读取图像
img = cv2.imread(‘image.jpg’) # 确保图片文件在当前目录下或提供完整路径
if img is None:
print(“无法读取图像,请检查路径或文件是否存在。”)
else:
# 显示图像
cv2.imshow(‘Original Image’, img)
cv2.waitKey(0) # 等待按键,0表示无限等待
cv2.destroyAllWindows() # 销毁所有窗口
# 保存图像
cv2.imwrite('new_image.png', img)
print("图像已保存为 new_image.png")
“`
cv2.imread(filename, flags):读取图像。flags参数可控制读取方式(如灰度图cv2.IMREAD_GRAYSCALE)。cv2.imshow(winname, mat):在指定窗口中显示图像。cv2.waitKey(delay):等待用户按键,返回按键的 ASCII 值。delay为毫秒,0表示无限等待。cv2.destroyAllWindows():销毁所有 OpenCV 窗口。cv2.imwrite(filename, img):保存图像。
3. 图像的基本属性与访问
图像是高度、宽度和通道数的 NumPy 数组。
“`python
print(“图像尺寸 (高, 宽, 通道):”, img.shape) # 例如 (400, 600, 3)
print(“图像像素数量:”, img.size)
print(“图像数据类型:”, img.dtype) # 通常是 uint8
访问像素 (B, G, R 顺序)
pixel = img[100, 50] # 访问 (100, 50) 坐标的像素值
print(“像素 (100, 50) 的 BGR 值:”, pixel)
修改像素
img[100, 50] = [255, 0, 0] # 将该像素设为蓝色
“`
注意:OpenCV 默认的颜色通道顺序是 BGR (Blue, Green, Red),而不是常见的 RGB。
4. 图像基本操作:缩放、裁剪、颜色空间转换
“`python
缩放图像
resized_img = cv2.resize(img, (200, 150)) # 缩放到宽200,高150
或者按比例缩放
scale_percent = 50
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
dim = (width, height)
scaled_img = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
裁剪图像 (Numpy 切片操作)
cropped_img = img[50:150, 100:300] # 从行50到149,列100到299
颜色空间转换
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换为灰度图
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 转换为 HSV 颜色空间
cv2.imshow(‘Resized Image’, resized_img)
cv2.imshow(‘Cropped Image’, cropped_img)
cv2.imshow(‘Grayscale Image’, gray_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
5. 绘制图形与文本
OpenCV 可以在图像上绘制点、线、矩形、圆形和文本。
“`python
blank_img = np.zeros((400, 600, 3), np.uint8) # 创建一个黑色空白图像
绘制线
cv2.line(blank_img, (0, 0), (600, 400), (0, 255, 0), 2) # 绿色,2像素粗
绘制矩形
cv2.rectangle(blank_img, (100, 50), (300, 200), (255, 0, 0), -1) # 蓝色,-1表示填充
绘制圆形
cv2.circle(blank_img, (450, 300), 70, (0, 0, 255), 3) # 红色,3像素粗
绘制文本
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(blank_img, ‘Hello OpenCV!’, (50, 380), font, 1, (255, 255, 255), 2, cv2.LINE_AA)
cv2.imshow(‘Drawing’, blank_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
二、核心图像处理技术
1. 阈值化 (Thresholding)
将图像转换为二值图像,常用于图像分割。
“`python
将彩色图像转为灰度图,以便进行阈值处理
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
简单阈值化
ret, thresh1 = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 像素值大于127设为255,否则0
cv2.imshow(‘Binary Threshold’, thresh1)
自适应阈值化 (更适合光照不均的图像)
thresh2 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
cv2.imshow(‘Adaptive Threshold’, thresh2)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
2. 图像平滑与模糊 (Smoothing/Blurring)
减少图像噪声,常用滤波器有均值滤波、高斯滤波和中值滤波。
“`python
均值滤波
blur_mean = cv2.blur(img, (5, 5))
高斯滤波 (最常用,保留边缘细节)
blur_gaussian = cv2.GaussianBlur(img, (5, 5), 0)
中值滤波 (对椒盐噪声效果好)
blur_median = cv2.medianBlur(img, 5)
cv2.imshow(‘Original’, img)
cv2.imshow(‘Mean Blur’, blur_mean)
cv2.imshow(‘Gaussian Blur’, blur_gaussian)
cv2.imshow(‘Median Blur’, blur_median)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
3. 边缘检测 (Edge Detection)
识别图像中亮度变化剧烈的区域。Canny 边缘检测是其中的经典算法。
python
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 100, 200) # 两个阈值用于边缘连接和强度判断
cv2.imshow('Canny Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
4. 轮廓检测 (Contour Detection)
在二值图像中查找连续的曲线,通常用于形状分析和目标识别。
“`python
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
查找轮廓
cv2.findContours 会修改输入图像,所以通常复制一份
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
绘制所有轮廓
contour_img = img.copy()
cv2.drawContours(contour_img, contours, -1, (0, 255, 0), 2) # -1表示绘制所有轮廓
cv2.imshow(‘Contours’, contour_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
5. 图像直方图 (Histograms)
统计图像中像素强度的分布,常用于图像增强、对比度调整和图像比较。
“`python
import matplotlib.pyplot as plt
计算灰度图像直方图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
hist_gray = cv2.calcHist([gray], [0], None, [256], [0, 256])
计算彩色图像每个通道的直方图
color = (‘b’,’g’,’r’)
for i, col in enumerate(color):
histr = cv2.calcHist([img],[i],None,[256],[0,256])
plt.plot(histr,color = col)
plt.xlim([0,256])
plt.title(‘Color Image Histogram’)
plt.show()
直方图均衡化 (增强图像对比度)
equalized_gray = cv2.equalizeHist(gray)
cv2.imshow(‘Original Gray’, gray)
cv2.imshow(‘Equalized Gray’, equalized_gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
三、进阶实践:高级功能与应用
1. 特征点检测与描述
特征点是图像中具有独特、可区分性的点,它们在图像变换(如旋转、缩放)后仍能保持稳定。OpenCV 提供了多种算法,如 SIFT (Scale-Invariant Feature Transform)、SURF (Speeded Up Robust Features) 和 ORB (Oriented FAST and Rotated BRIEF)。ORB 是 SIFT 和 SURF 的开源替代品。
“`python
以 ORB 为例进行特征点检测
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
orb = cv2.ORB_create()
kp, des = orb.detectAndCompute(gray_img, None) # kp是关键点,des是描述符
在图像上绘制关键点
kp_img = cv2.drawKeypoints(img, kp, None, color=(0, 255, 0), flags=0)
cv2.imshow(‘ORB Keypoints’, kp_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
特征匹配 (通常用于图像拼接、目标识别)
obj_img, scene_img 是两张不同的图像
kp1, des1 = orb.detectAndCompute(obj_img, None)
kp2, des2 = orb.detectAndCompute(scene_img, None)
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) # 暴力匹配器
matches = bf.match(des1, des2)
matches = sorted(matches, key = lambda x:x.distance)
matched_img = cv2.drawMatches(obj_img, kp1, scene_img, kp2, matches[:10], None, flags=2)
cv2.imshow(‘Matches’, matched_img)
“`
2. 目标检测 (Object Detection)
OpenCV 支持多种目标检测方法,从传统的基于特征的方法到现代的深度学习方法。
a. Haar 级联分类器 (Cascade Classifiers)
主要用于人脸检测,速度快,但准确率不如深度学习模型。
“`python
加载人脸检测器 (XML 文件通常在 OpenCV 安装目录的 haarcascades 文件夹下)
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + ‘haarcascade_frontalface_default.xml’)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.1, 4) # scaleFactor, minNeighbors
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
cv2.imshow(‘Face Detection’, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
b. 基于深度学习的目标检测 (DNN Module)
OpenCV 的 dnn 模块允许加载预训练的深度学习模型,如 YOLO、SSD 等,进行更准确、多类别的目标检测。这通常需要模型文件(如 .weights, .cfg 或 .pb)和类别文件。
“`python
这是一个概念性示例,需要下载具体的模型文件
net = cv2.dnn.readNetFromDarknet(‘yolov3.cfg’, ‘yolov3.weights’)
output_layers = net.getUnconnectedOutLayersNames()
blob = cv2.dnn.blobFromImage(img, 1/255.0, (416, 416), swapRB=True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)
# 后处理 outs 以获取边界框和置信度
# …
“`
3. 图像分割 (Image Segmentation)
将图像分割成多个区域或对象,例如前景/背景分离。
“`python
GrabCut 算法 (交互式前景提取)
mask = np.zeros(img.shape[:2], np.uint8)
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
定义一个初始矩形区域 (这里假设前景在此区域内)
rect = (50, 50, img.shape[1]-100, img.shape[0]-100)
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0), 0, 1).astype(‘uint8’)
segmented_img = img * mask2[:, :, np.newaxis]
cv2.imshow(‘Segmented Image (GrabCut)’, segmented_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
4. 图像拼接 (Image Stitching)
将多张有重叠区域的图像拼接成一张全景图。
“`python
同样是概念性示例,需要多张图片
stitcher = cv2.Stitcher_create()
status, stitched_img = stitcher.stitch([img1, img2, img3])
if status == cv2.Stitcher_OK:
cv2.imshow(‘Stitched Image’, stitched_img)
else:
print(“图像拼接失败:”, status)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
5. 视频处理与分析
OpenCV 提供了强大的视频读写和处理能力。
“`python
读取视频
cap = cv2.VideoCapture(‘video.mp4’) # 0 代表默认摄像头
if not cap.isOpened():
print(“无法打开视频或摄像头”)
exit()
while True:
ret, frame = cap.read() # 读取一帧
if not ret:
print("视频帧读取完毕或无法读取。")
break
# 在这里可以对每一帧进行图像处理,例如转换为灰度
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('Video Frame', frame)
cv2.imshow('Gray Video Frame', gray_frame)
if cv2.waitKey(25) & 0xFF == ord('q'): # 每25毫秒显示一帧,按'q'退出
break
cap.release() # 释放资源
cv2.destroyAllWindows()
“`
a. 运动检测 (Motion Detection)
通过比较连续帧来检测图像中的变化。
“`python
基于背景减除的运动检测
fgbg = cv2.createBackgroundSubtractorMOG2() # 高斯混合模型背景减除器
while True:
ret, frame = cap.read()
if not ret: break
fgmask = fgbg.apply(frame)
cv2.imshow(‘Motion Mask’, fgmask)
if cv2.waitKey(30) & 0xFF == ord(‘q’): break
cap.release()
cv2.destroyAllWindows()
“`
b. 对象跟踪 (Object Tracking)
跟踪视频中特定对象的移动。OpenCV 提供了多种跟踪器(如 CSRT, KCF, MedianFlow 等)。
“`python
tracker = cv2.TrackerCSRT_create()
ret, frame = cap.read()
bbox = cv2.selectROI(frame, False) # 手动选择 ROI
tracker.init(frame, bbox)
while True:
ret, frame = cap.read()
if not ret: break
success, bbox = tracker.update(frame)
if success:
p1 = (int(bbox[0]), int(bbox[1]))
p2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))
cv2.rectangle(frame, p1, p2, (255, 0, 0), 2, 1)
else:
cv2.putText(frame, “Tracking failure detected”, (100,80), cv2.FONT_HERSHEY_SIMPLEX, 0.75,(0,0,255),2)
cv2.imshow(“Tracking”, frame)
if cv2.waitKey(30) & 0xFF == ord(‘q’): break
cap.release()
cv2.destroyAllWindows()
“`
四、总结
Python 和 OpenCV 的结合为计算机视觉的开发提供了无与伦比的便利和强大功能。从图像的读写、基本操作,到阈值化、边缘检测、轮廓分析等核心处理技术,再到特征点检测、目标检测、图像分割和视频分析等进阶应用,OpenCV 几乎涵盖了计算机视觉领域的所有基础与大部分高级任务。
掌握这些基础知识和进阶实践,将使你能够解决各种复杂的视觉挑战,无论是构建智能监控系统、开发 AR 应用程序,还是进行科学研究,Python-OpenCV 都是你不可或缺的利器。随着深度学习技术的飞速发展,OpenCV 也不断集成最新的模型和算法,未来其在计算机视觉领域的应用将更加广阔。