【图像处理速通】OpenCV 核心操作一网打尽:从像素到 SIFT 特征提取
前言
图像处理是计算机视觉的基石,OpenCV 是这一领域最流行的工具库。本文旨在用一篇文章带你快速打通图像处理的常用操作,从基础像素概念一路深入到轮廓检测、直方图均衡、傅里叶变换,再到 Harris 角点和 SIFT 特征提取。无论你是初学者还是需要快速复习,这篇“速通指南”都能帮你高效梳理核心知识点。
1. 图像的基础:像素与颜色通道
1.1 像素的本质
计算机眼中的图像由像素构成,每个像素本质上是一个数值,这个数值表示亮度。对于最常见的 8 位图像,范围是0~255:
0:纯黑(没有亮度)
255:纯白(最高亮度)
1.2 颜色通道
彩色图像通常使用RGB三个颜色通道,每个通道独立记录亮度。形状可以表示为[H, W, 3]。
灰度图只有一个通道,形状为
[H, W],许多检测任务(如轮廓、特征提取)都先转为灰度图进行处理。
2. 图像的读取、显示与保存
2.1 读取图像
python
import cv2 # 彩色模式读取(默认) img_color = cv2.imread('cat.jpg', cv2.IMREAD_COLOR) # 灰度模式读取 img_gray = cv2.imread('cat.jpg', cv2.IMREAD_GRAYSCALE)OpenCV 默认读入的颜色顺序是BGR,用matplotlib显示时需要转换。
2.2 转灰度图
如果已经读入彩色图,可以随时转换:
python
img_gray = cv2.cvtColor(img_color, cv2.COLOR_BGR2GRAY)
2.3 显示图像
OpenCV 显示窗口:
python
def cv_show(name, img): cv2.imshow(name, img) cv2.waitKey(0) cv2.destroyAllWindows()
也可用matplotlib绘图:
python
import matplotlib.pyplot as plt plt.imshow(img[:,:,::-1]) # BGR 转 RGB plt.show()
2.4 保存图像
python
cv2.imwrite('output.jpg', img)2.5 图像属性
python
print(img.shape) # (高度, 宽度, 通道数) print(img.size) # 总像素数 = H*W*C print(img.dtype) # 数据类型,如 uint8
3. 视频读取
python
vc = cv2.VideoCapture('test.mp4') while vc.isOpened(): ret, frame = vc.read() if not ret: break cv2.imshow('video', frame) if cv2.waitKey(30) & 0xFF == 27: # 按 Esc 退出 break vc.release() cv2.destroyAllWindows()waitKey(30)表示每帧间隔 30ms,对应约 33 fps,流畅播放。
4. 通道分离与合并
4.1 分离
python
b, g, r = cv2.split(img)
4.2 合并
python
img_merged = cv2.merge((b, g, r))
4.3 只保留某一通道
将其他通道置 0,例如只显示蓝色分量:
python
blue_only = img.copy() blue_only[:, :, 1] = 0 # 绿通道置0 blue_only[:, :, 2] = 0 # 红通道置0
5. 图像的数值运算与融合
5.1 直接加法(溢出取余)
python
img2 = img + 10 # 超过255会取模,如 256 → 0
5.2 图像融合
两张图像相加融合前,需保证尺寸一致(使用cv2.resize)。
python
img1 = cv2.imread('1.jpg') img2 = cv2.imread('2.jpg') img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0])) fusion = cv2.addWeighted(img1, 0.6, img2, 0.4, 0) # 加权融合6. 图像边界填充
python
# top, bottom, left, right img_padded = cv2.copyMakeBorder(img, 50, 50, 50, 50, cv2.BORDER_CONSTANT, value=0)
7. 阈值处理
python
ret, binary = cv2.threshold(src, thresh, maxval, type)
常用type:
cv2.THRESH_BINARY:大于阈值取 maxval,否则 0cv2.THRESH_BINARY_INV:反向cv2.THRESH_TRUNC:截断cv2.THRESH_TOZERO:小于阈值置零
阈值操作常用于将灰度图转为二值图,为后续轮廓检测做准备。
8. 图像平滑(滤波)
平滑旨在去除噪声,为边缘检测等任务做准备。
| 滤波方式 | 函数 | 特点 |
|---|---|---|
| 均值滤波 | cv2.blur(img, (3,3)) | 简单平均,图像变模糊 |
| 方框滤波 | cv2.boxFilter(img, -1, (3,3)) | 若未归一化,像素值会叠加(通常需要归一化) |
| 高斯滤波 | cv2.GaussianBlur(img, (3,3), 1) | 中心权重更大,离中心越远的点影响越小 |
| 中值滤波 | cv2.medianBlur(img, 3) | 用邻域像素中值替换,适合椒盐噪声 |
python
blur = cv2.blur(img, (5,5)) gaussian = cv2.GaussianBlur(img, (5,5), 0) median = cv2.medianBlur(img, 5)
9. 形态学操作
形态学主要用于处理二值图像,提取形状或去除噪声。
腐蚀(
cv2.erode):边界向内收缩,可去除细小噪点。膨胀(
cv2.dilate):边界向外扩张,可填补空洞。
开运算与闭运算
开运算:先腐蚀后膨胀 → 去除毛刺、分离细小连接。
闭运算:先膨胀后腐蚀 → 填充空洞、连接邻近物体。
python
kernel = np.ones((5,5), np.uint8) opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
形态学梯度(轮廓信息)
python
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel) # 等价于 膨胀 - 腐蚀
礼帽与黑帽
礼帽:原图 - 开运算 → 得到“刺”或亮区细节
黑帽:闭运算 - 原图 → 得到暗区轮廓
python
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
10. 图像梯度与边缘检测
10.1 梯度算子
Sobel 算子:一阶微分,抗噪较好
Scharr 算子:Sobel 的增强版,核更大
Laplacian 算子:二阶微分,对噪声敏感
python
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) scharrx = cv2.Scharr(img, cv2.CV_64F, 1, 0) laplacian = cv2.Laplacian(img, cv2.CV_64F)
10.2 Canny 边缘检测
最经典的边缘检测算法,步骤包括高斯滤波、梯度计算、非极大值抑制和双阈值筛选。
python
edges = cv2.Canny(img, threshold1=50, threshold2=150)
11. 图像金字塔
图像金字塔是同一图像不同分辨率的集合,用于多尺度分析。
11.1 高斯金字塔
向下采样(
cv2.pyrDown):尺寸减半,先高斯模糊再去掉偶数行列。向上采样(
cv2.pyrUp):尺寸加倍,用 0 填充后高斯模糊。
python
down = cv2.pyrUp(img) # 放大(变模糊) up = cv2.pyrDown(img) # 缩小
11.2 拉普拉斯金字塔
拉普拉斯金字塔由高斯金字塔层间相减得到,更关注高频细节,常用于图像融合。
12. 轮廓检测
轮廓检测要求输入为二值图像(通常先灰度化,再阈值分割)。
python
# 寻找轮廓 contours, hierarchy = cv2.findContours(binary_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 绘制轮廓(会覆盖原图,建议先复制) draw_img = img.copy() res = cv2.drawContours(draw_img, contours, -1, (0, 255, 0), 3) cv_show('Contours', res)轮廓特征
python
cnt = contours[0] # 取第一个轮廓 area = cv2.contourArea(cnt) # 面积 perimeter = cv2.arcLength(cnt, True) # 周长(True表示闭合) epsilon = 0.1 * perimeter # 近似精度 approx = cv2.approxPolyDP(cnt, epsilon, True) # 轮廓多边形近似
13. 模板匹配
将模板图像在待搜索图像上滑动,计算匹配度。
python
result = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) # 画出匹配区域 h, w = template.shape[:2] top_left = max_loc # 归一化相关系数匹配取最大值位置 bottom_right = (top_left[0]+w, top_left[1]+h) cv2.rectangle(img, top_left, bottom_right, 255, 2)
不同匹配方法:TM_SQDIFF(平方差最小)、TM_CCORR_NORMED、TM_CCOEFF_NORMED,推荐使用归一化方法,结果更稳定。
14. 直方图与均衡化
14.1 计算直方图
python
hist = cv2.calcHist([img], channels=[0], mask=None, histSize=[256], ranges=[0, 256])
14.2 Mask 操作
只统计感兴趣区域的直方图:
python
mask = np.zeros(img.shape[:2], np.uint8) mask[100:300, 100:300] = 255 masked_hist = cv2.calcHist([img], [0], mask, [256], [0, 256])
14.3 直方图均衡化
全局均衡化:增强对比度,但可能丢失细节。
python
equ = cv2.equalizeHist(gray_img)
自适应均衡化(
CLAHE):分块均衡,限制对比度过度放大。python
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) clahe_img = clahe.apply(gray_img)
15. 傅里叶变换
傅里叶变换将图像从空间域转换到频率域。
低频分量:图像中变化缓慢的灰度分量(如背景、大块区域)
高频分量:变化剧烈的灰度分量(如边缘、噪声)
低通滤波器:保留低频,抑制高频 → 图像变模糊
高通滤波器:保留高频,抑制低频 → 提取边缘与细节
python
import numpy as np f = np.fft.fft2(gray) # 傅里叶变换 fshift = np.fft.fftshift(f) # 将零频移到中心 # 设计低通/高通掩膜并相乘,再做逆变换恢复图像...
16. 图像特征检测
16.1 Harris 角点检测
角点是水平和垂直方向灰度都变化剧烈的点。基本思想是用一个小窗口在图像上滑动,观察窗口内的灰度变化。
python
gray = np.float32(gray) dst = cv2.cornerHarris(gray, blockSize=2, ksize=3, k=0.04) img[dst > 0.01*dst.max()] = [0, 0, 255] # 标记角点
16.2 SIFT 特征提取
SIFT 具有尺度不变性和旋转不变性,步骤包括:
构建尺度空间,寻找 DoG 空间的极值点。
定位真正的极值点(泰勒展开精确定位),消除边界响应。
为关键点分配方向,并用直方图统计邻域梯度,生成特征描述符。
旋转坐标轴以保证旋转不变性。
注意:SIFT 曾经受专利保护,需在 opencv-contrib 中从
cv2.xfeatures2d.SIFT_create()调用。
但自 OpenCV 4.4.0 起,专利到期,SIFT 已回归主库,可直接使用:
python
sift = cv2.SIFT_create() kp = sift.detect(gray, None) # 检测关键点 kp, des = sift.compute(gray, kp) # 计算描述符 # 或者一步到位 kp, des = sift.detectAndCompute(gray, None) # 绘制关键点 img_kp = cv2.drawKeypoints(img, kp, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) cv_show('SIFT', img_kp)结语
本文从最基本的像素与通道起步,逐步深入形态学、滤波、梯度、金字塔、轮廓、直方图、频域变换,直到角点和 SIFT 特征检测,覆盖了 OpenCV 图像处理的绝大多数高频操作。将这份“速通笔记”收为己用,配合实际代码练习,相信你能在短时间内建立起图像处理的完整知识框架。
🌟 速通不是终点,而是起点。掌握这些核心轮子后,你完全可以驾驭更复杂的视觉任务,如目标检测、图像分割、全景拼接等。
如果觉得有帮助,欢迎点赞收藏,让更多人一起速通图像处理!
