【图像处理速通】OpenCV 核心操作一网打尽:从像素到 SIFT 特征提取

📅 2026/7/29 10:51:27 👁️ 阅读次数 📝 编程学习
【图像处理速通】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,否则 0

  • cv2.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_NORMEDTM_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 具有尺度不变性和旋转不变性,步骤包括:

  1. 构建尺度空间,寻找 DoG 空间的极值点。

  2. 定位真正的极值点(泰勒展开精确定位),消除边界响应。

  3. 为关键点分配方向,并用直方图统计邻域梯度,生成特征描述符。

  4. 旋转坐标轴以保证旋转不变性。

注意: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 图像处理的绝大多数高频操作。将这份“速通笔记”收为己用,配合实际代码练习,相信你能在短时间内建立起图像处理的完整知识框架。

🌟 速通不是终点,而是起点。掌握这些核心轮子后,你完全可以驾驭更复杂的视觉任务,如目标检测、图像分割、全景拼接等。

如果觉得有帮助,欢迎点赞收藏,让更多人一起速通图像处理!