【参考】https://github.com/opencv/opencv/tree/4.x/samples/python
OpenCV (Open Source Computer Vision Library) 是一个开源的计算机视觉和机器学习软件库。下面将从基础到高阶介绍如何使用Python中的OpenCV进行图像处理。
首先需要安装OpenCV库:
pip install opencv-python # 基础模块 pip install opencv-contrib-python # 包含额外模块
原理:imread()
函数通过解码图像文件将像素数据加载到内存中,形成多维数组(H×W×C)。imwrite()
则执行反向编码过程。
应用场景:
图像预处理流水线的第一步和最后一步
数据集加载和结果保存
图像格式转换(如.jpg转.png)
import cv2 # 读取图像 img = cv2.imread('image.jpg') # 默认读取BGR格式 # 显示图像 cv2.imshow('Image', img) cv2.waitKey(0) # 等待任意按键 cv2.destroyAllWindows() # 关闭所有窗口 # 保存图像 cv2.imwrite('output.jpg', img)
print("图像形状:", img.shape) # (高度, 宽度, 通道数) print("图像大小:", img.size) # 总像素数 print("图像数据类型:", img.dtype) # 数据类型
原理:基于不同颜色空间的数学转换公式:
RGB→灰度:Y = 0.299R + 0.587G + 0.114B
RGB→HSV:通过计算色相(H)、饱和度(S)、明度(V)分量
应用场景:
灰度化:简化处理复杂度(如边缘检测)
HSV空间:颜色识别(交通标志检测)
LAB空间:肤色检测
# BGR转灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# BGR转HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# BGR转RGB
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
原理:通过2×3变换矩阵实现线性变换:
[x'] [a b c] [x] [y'] = [d e f] [y] [1 ] [0 0 1] [1]
包括平移、旋转、缩放和剪切
应用场景:
图像校正(文档扫描)
数据增强(深度学习训练)
视觉SLAM中的图像对齐
# 裁剪图像 (y, x) cropped = img[100:400, 200:500] # 缩放图像 resized = cv2.resize(img, (new_width, new_height)) # 保持宽高比缩放 h, w = img.shape[:2] aspect_ratio = w / h new_height = 300 new_width = int(new_height * aspect_ratio) resized = cv2.resize(img, (new_width, new_height))
(h, w) = img.shape[:2] center = (w // 2, h // 2) # 旋转矩阵 M = cv2.getRotationMatrix2D(center, 45, 1.0) # 45度,缩放1.0 rotated = cv2.warpAffine(img, M, (w, h))
# 简单阈值 ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 自适应阈值 thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) # Otsu's 二值化 ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
原理:使用3×3矩阵实现投影变换,保持直线性但允许比例变化:
[x'] [a b c] [x] [y'] = [d e f] [y] [w ] [g h 1] [1]
应用场景:
车牌识别中的视角校正
AR应用中的虚拟物体植入
全景图像拼接
原理:卷积运算,使用核矩阵与图像局部区域做点乘求和:
G(i,j) = ∑∑ K(m,n)·I(i+m,j+n)
应用场景:
高斯滤波:降噪(人脸识别预处理)
均值滤波:简单模糊(背景虚化)
Sobel滤波:边缘检测(工业检测)
原理:基于排序统计而非线性组合:
中值滤波:取邻域中值
双边滤波:结合空间距离和像素值相似性
应用场景:
中值滤波:椒盐噪声去除(旧照片修复)
双边滤波:保边平滑(美颜相机)
# 均值滤波 blur = cv2.blur(img, (5,5)) # 高斯滤波 blur = cv2.GaussianBlur(img, (5,5), 0) # 中值滤波 median = cv2.medianBlur(img, 5) # 双边滤波 (保持边缘) blur = cv2.bilateralFilter(img, 9, 75, 75)
原理:
Sobel:一阶导数近似,使用[-1 0 1; -2 0 2; -1 0 1]核
Laplacian:二阶导数,对噪声敏感
应用场景:
Sobel:快速边缘检测(实时系统)
Laplacian:斑点检测(医学影像)
原理:
高斯滤波去噪
计算梯度幅值和方向
非极大值抑制
双阈值检测
应用场景:
精密测量(PCB板检测)
物体识别(自动驾驶车道检测)
# Sobel算子 sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=5) sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=5) # Laplacian算子 laplacian = cv2.Laplacian(gray, cv2.CV_64F) # Canny边缘检测 edges = cv2.Canny(gray, 100, 200) # 阈值1, 阈值2
原理:基于集合论的结构元素操作:
腐蚀:保留结构元素完全包含的区域
膨胀:保留结构元素接触到的区域
应用场景:
腐蚀:分离粘连物体(细胞计数)
膨胀:填补空洞(文字修复)
开运算:去除小噪点(指纹识别)
原理:
顶帽:原图 - 开运算(突出亮细节)
黑帽:闭运算 - 原图(突出暗细节)
应用场景:
顶帽变换:光照不均匀校正(医学影像)
形态学梯度:边缘提取(工业零件检测)
kernel = np.ones((5,5), np.uint8) # 腐蚀 erosion = cv2.erode(img, kernel, iterations=1) # 膨胀 dilation = cv2.dilate(img, kernel, iterations=1) # 开运算 (先腐蚀后膨胀) opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) # 闭运算 (先膨胀后腐蚀) closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) # 形态学梯度 gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
Harris角点:
基于自相关矩阵的特征值分析
响应函数:R = det(M) - k·trace(M)²
应用场景:
图像配准(全景拼接)
视觉里程计(机器人导航)
SIFT特征:
尺度空间极值检测
关键点精确定位
方向分配
描述子生成
应用场景:
商标识别(侵权检测)
特定目标检索(图像数据库)
# SIFT特征 sift = cv2.SIFT_create() keypoints, descriptors = sift.detectAndCompute(gray, None) # SURF特征 surf = cv2.xfeatures2d.SURF_create(400) keypoints, descriptors = surf.detectAndCompute(gray, None) # ORB特征 orb = cv2.ORB_create() keypoints, descriptors = orb.detectAndCompute(gray, None) # 绘制关键点 img_keypoints = cv2.drawKeypoints(img, keypoints, None, color=(0,255,0))
# 创建匹配器 bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) # 匹配描述子 matches = bf.match(des1, des2) # 按照距离排序 matches = sorted(matches, key=lambda x:x.distance) # 绘制匹配结果 img_matches = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=2)
Otsu算法:
最大化类间方差
自动确定最优阈值
应用场景:
文档二值化(OCR预处理)
前景提取(监控视频分析)
原理:
将图像视为地形图
从标记点开始"淹没"形成分割区域
应用场景:
细胞分割(生物医学)
矿石粒度分析(矿业)
# 分水岭算法
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# 噪声去除
kernel = np.ones((3,3), np.uint8)
opening = cv2.morphologyEx(thresh, 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)
markers = markers + 1
markers[unknown == 255] = 0
# 应用分水岭算法
markers = cv2.watershed(img, markers)
img[markers == -1] = [255,0,0]
# 查找轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv2.drawContours(img, contours, -1, (0,255,0), 3)
# 轮廓特征
for cnt in contours:
# 面积
area = cv2.contourArea(cnt)
# 周长
perimeter = cv2.arcLength(cnt, True)
# 近似多边形
epsilon = 0.01 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
# 凸包
hull = cv2.convexHull(cnt)
# 边界矩形
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
# 最小外接矩形
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(img, [box], 0, (0,0,255), 2)
# 最小外接圆
(x,y), radius = cv2.minEnclosingCircle(cnt)
center = (int(x), int(y))
radius = int(radius)
cv2.circle(img, center, radius, (255,0,0), 2)
Haar级联:
使用积分图快速计算矩形特征
AdaBoost分类器级联
应用场景:
人脸识别系统(门禁)
表情分析(人机交互)
# 加载预训练模型
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
# 检测人脸
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), (255,0,0), 2)
# 创建跟踪器
tracker = cv2.TrackerCSRT_create()
# 初始化跟踪器
bbox = cv2.selectROI("Tracking", img, False)
tracker.init(img, bbox)
while True:
# 更新跟踪器
success, bbox = tracker.update(img)
if success:
# 绘制跟踪框
p1 = (int(bbox[0]), int(bbox[1]))
p2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))
cv2.rectangle(img, p1, p2, (255,0,0), 2, 1)
else:
cv2.putText(img, "Tracking failure", (100,80),
cv2.FONT_HERSHEY_SIMPLEX, 0.75,(0,0,255),2)
cv2.imshow("Tracking", img)
if cv2.waitKey(1) & 0xff == ord('q'):
break
# 初始化拼接器
stitcher = cv2.Stitcher_create()
# 拼接图像
status, panorama = stitcher.stitch([img1, img2, img3])
if status == cv2.Stitcher_OK:
cv2.imshow("Panorama", panorama)
else:
print("拼接失败 (错误码 = %d)" % status)
DNN模块:
加载预训练模型(TensorFlow/PyTorch)
使用blobFromImage准备输入
应用场景:
实时目标检测(智能监控)
场景理解(自动驾驶)
# 加载模型
net = cv2.dnn.readNetFromTensorflow('model.pb', 'graph.pbtxt')
# 准备输入
blob = cv2.dnn.blobFromImage(img, scalefactor=1.0, size=(300, 300),
mean=(104.0, 177.0, 123.0), swapRB=True, crop=False)
# 前向传播
net.setInput(blob)
detections = net.forward()
# 处理输出
for i in range(detections.shape[2]):
confidence = detections[0, 0, i, 2]
if confidence > 0.5:
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
cv2.rectangle(img, (startX, startY), (endX, endY), (0, 255, 0), 2)
cap = cv2.VideoCapture(0) # 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()
使用UMat:OpenCV的透明API,可以自动使用OpenCL加速
img_umat = cv2.UMat(img) blur = cv2.GaussianBlur(img_umat, (5,5), 0) result = blur.get()
避免不必要的复制:
# 不好的做法 img2 = img.copy() # 好的做法 - 使用视图 img2 = img[:]
批量处理:对视频或图像序列处理时,尽量批量操作
使用适当的图像数据类型:
# 对于0-255范围的图像,使用uint8节省内存 img = img.astype(np.uint8)
多线程处理:对于多图像处理,可以使用Python的multiprocessing或concurrent.futures
处理需求 | 推荐算法 | 优势 | 局限性 |
---|---|---|---|
快速去噪 | 中值滤波 | 有效去除椒盐噪声 | 边缘模糊 |
精确边缘 | Canny | 低错误率 | 计算量大 |
特征匹配 | ORB | 实时性好 | 旋转不变性较弱 |
复杂分割 | 分水岭 | 适应不规则形状 | 需要标记 |
实时检测 | Haar级联 | 速度快 | 精度一般 |
高精度检测 | DNN | 准确率高 | 需要GPU |
理解这些原理可以帮助开发者:
合理选择算法组合
优化参数配置
解决特定场景问题
开发创新性应用
OpenCV是一个功能强大的计算机视觉库,从基础的图像读写、颜色空间转换,到高级的特征检测、目标跟踪和深度学习集成,提供了丰富的功能。掌握这些技术可以解决各种图像处理和计算机视觉问题。随着实践的深入,可以结合具体应用场景,将这些技术组合使用,开发出更复杂的视觉应用系统。