计算机视觉(传统篇)
前言:这篇blog的最初写作目的是为了把cv初步的方法和其代码一同学习,但是后期发现特征提取部分的方法还是过于复杂的,一篇文章写完不太现实。所以决定这篇文章就按照大纲形式收集下cv各个模块的常用方法以及初步代码(不保真),以做后续查找使用。 PS:主要是机器学习部分的学习,没有涉及深度的内容,深度学习的处理之后会继续写。
图像和视频
图像的取样和量化
图像的取样与量化是数字图像处理的基础,用于将连续的现实世界图像转换为离散的数字形式。
取样(Sampling):
- 定义:将连续的空间信号(如现实世界的图像)分解为离散像素点网络
- 过程:通过在空间上以固定间隔(分辨率)采集图像的强度值,将连续图像分割为像素网格。例如,一个 1920x1080 的图像表示在水平和垂直方向上分别采样了 1920 和 1080 次。 #### 量化(Quantization):
- 定义:将连续的像素强度值(通常是光强或颜色值)映射到离散的数值范围。
- 过程:将像素的强度值(通常为浮点数)离散化为有限的整数级别。例如,8位灰度图像将强度值量化为 0 到 255 的 256 个级别。
- 影响:量化级别越高,图像的灰度或颜色表现越细腻,但存储需求也增加。过低的量化级别会导致伪轮廓(False Contouring),即图像出现明显的颜色或灰度分层。
- 数学表示:假设原始强度值范围为\([I_{\text{min}}, I_{\text{max}}]\),量化为 \(L\) 级,量化公式为:\[I_{\text{quantized}} = \text{round}\left(\frac{I - I_{\text{min}}}{I_{\text{max}} - I_{\text{min}}} \cdot (L-1)\right)\]
1
2
3img = cv2.imread('image.jpg',cv2.IMREAD_GRAYSCALE)
levels=16 # 减少灰度级别到16级
quantized_img = np.floor_divide(img, 256 // levels) * (256 // levels) # np.floor_divide 取整 // 除法取整
滤波
滤波是图像处理中用于增强、平滑或提取特征的操作,通过对图像像素值进行加权运算来实现。
- 定义:滤波通过一个卷积核(滤波器)对图像进行处理,改变像素值以实现平滑、锐化、边缘检测等效果。
- 类型:
- 低通滤波(Low-pass Filtering):平滑图像,减少噪声。比如说中值滤波、均值滤波、高斯滤波。
- 高通滤波(High-pass Filtering):突出图像的高频部分,如边缘或细节,常用于边缘检测(如 Sobel 滤波器)。
- 带通滤波:保留特定频率范围,常用于特征提取。
- 实现:通过卷积操作(详见“卷积”部分)将滤波核应用于图像。
1 | blur=cv2.blur(img,(3*3)) # 均值滤波 |
直方图
直方图是统计图像像素强度分布的工具,用于分析图像的亮度或颜色特性。
定义:直方图表示图像中每个强度级别(或颜色通道值)的像素数量。
- 对于灰度图像,直方图通常表示 0 到 255 的灰度级别的像素分布。
- 对于彩色图像,可以分别对 R、G、B 通道生成直方图。
用途:
- 分析图像的亮度分布(例如,判断图像是否过暗或过亮)。
- 作为特征用于图像检索或分类。
- 指导直方图均衡化等增强算法。
计算:统计每个强度级别的像素数量,绘制为柱状图(或曲线)。
- 数学表示:对于灰度值 iii(0 到 255),直方图 h(i)h(i)h(i) 表示强度值为 iii 的像素数。 ### 上采样
1
2# 计算直方图
hist = cv2.calcHist([img], [0], None, [256], [0, 256])
- 数学表示:对于灰度值 iii(0 到 255),直方图 h(i)h(i)h(i) 表示强度值为 iii 的像素数。
定义:增加图像的分辨率(像素数量),通常用于图像放大。
方法:
- 插值法:如最近邻插值、双线性插值或双三次插值(见“插值”部分)。
- 超分辨率:使用机器学习模型(如深度卷积网络)预测高分辨率细节。
应用:
- 图像放大(例如,显示器适配)。
- 增强图像细节(例如,超分辨率重建)。
挑战:上采样可能引入模糊或伪影,需选择合适的插值或模型。
### 下采样1
2
3
4
5
6
7
8# 上采样(放大 2 倍)
upsampled = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR)
# cv2.resize(src, dsize, fx, fy, interpolation): 调整图像大小。
# - src: 输入图像。
# - dsize: 输出图像尺寸(若为 None,则由 fx, fy 决定)。
# - fx, fy: x 和 y 方向的缩放因子(如 fx=2 表示宽度放大 2 倍)。
# - interpolation: 插值方法,如 cv2.INTER_LINEAR(双线性插值)。
# - 返回: 调整大小后的图像。定义:减少图像的分辨率(像素数量),通常用于图像缩小或减少计算量。
方法:
- 直接抽样:每隔固定间隔取一个像素(可能导致混叠)。
- 平滑后抽样:先应用低通滤波(如高斯模糊)去除高频分量,再抽样以避免混叠。
应用:
- 图像压缩(减少存储需求)。
- 构建图像金字塔(用于多尺度分析)。
挑战:下采样会丢失细节,需平衡分辨率与信息保留。
1
2
3
4
5
6
7
8# 先高斯模糊以避免混叠
blurred = cv2.GaussianBlur(img, (5, 5), 0)
# 下采样(缩小 0.5 倍)
downsampled = cv2.resize(blurred, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_LINEAR)
# cv2.GaussianBlur(src, ksize, sigmaX): 应用高斯模糊。
# - src: 输入图像。
# - ksize: 核大小,元组 (width, height),必须为奇数(如 (5, 5))。
# - sigmaX: x 方向高斯核标准差,0 表示自动计算。
卷积
卷积是图像处理和机器学习中的核心操作,用于特征提取和滤波。
- 定义:通过一个小的滤波核(Kernel 或 Filter)在图像上滑动,计算核与图像区域的加权和,生成新的像素值。
- 数学表示: 对于图像\(I(x, y)\) 和核 \(K(m, n)\),卷积结果为: \(O(x, y) = \sum_{m} \sum_{n} I(x+m, y+n) \cdot K(m, n)\) 其中 \(O(x, y)\) 是输出图像的像素值。
- 应用:
- 图像平滑(均值滤波、高斯滤波)。
- 边缘检测(Sobel、Prewitt 算子)。
- 特征提取(卷积神经网络 CNN 的核心操作)。
- 注意:
- 核大小通常为奇数(如 3x3、5x5),以确保中心像素对称。
- 边界处理:常用填充(Padding)方式,如零填充或镜像填充。
1 | # 定义 3x3 锐化核 |
直方图均衡化算法
直方图均衡化是一种增强图像对比度的方法,通过重新分配像素强度值使直方图更均匀。
- 原理:
- 计算图像的灰度直方图。
- 计算累积分布函数(CDF,Cumulative Distribution Function): \[CDF(i) = \sum_{k=0}^{i} h(k)\] 其中 \(h(k)\) 是直方图值,\(i\)是灰度级别。
- 归一化 CDF 并映射到目标范围(通常为 0 到 255): \[I_{\text{new}}(x, y) = \text{round}\left(\frac{CDF(I(x, y)) - CDF_{\text{min}}}{N - 1} \cdot (L-1)\right)\]其中 \(N\) 是像素总数,\(L\)是量化级别数(如 256)。
- 步骤:
- 计算直方图 \(h(i)\)。
- 计算 CDF。
- 归一化并映射像素值。
- 效果:
- 增强图像对比度,尤其对低对比度图像效果显著。
- 可能放大噪声或导致不自然的对比度增强。
1
2# 直方图均衡化
equalized = cv2.equalizeHist(img)
最近邻差值(Nearest Neighbor Interpolation)
- 定义:一种简单的插值方法,用于上采样或下采样,选取距离目标点最近的像素值作为新像素值。
- 特点:
- 计算简单,速度快。
- 结果可能出现块状伪影(“马赛克”效应),不平滑。
- 应用:适合对像素级精度要求高的场景(如像素艺术放大)。 ### 单/双线性差值(Bilinear Interpolation)
1
2# 最近邻插值(放大 2 倍)
nearest = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_NEAREST) - 单线性插值:
- 定义:在单一维度上使用线性插值,基于相邻两个点的距离加权平均。
- 公式:对于点 \(x\) 在 \(x_0\) 和 \(x_1\) 之间,值 \(f(x)\) 为: \[ f(x) = f(x_0) + \frac{x - x_0}{x_1 - x_0} \cdot (f(x_1) - f(x_0)) \]
- 双线性插值:
- 定义:在二维空间上扩展单线性插值,使用四个邻近像素的加权平均。
- 公式:对目标点 \((x, y)\),基于四个角点 \((x_0, y_0), (x_0, y_1), (x_1, y_0), (x_1, y_1)\),计算: \[ f(x, y) = (1-w_x)(1-w_y)f(x_0, y_0) + w_x(1-w_y)f(x_1, y_0) + (1-w_x)w_y f(x_0, y_1) + w_x w_y f(x_1, y_1) \] 其中 \(w_x = \frac{x - x_0}{x_1 - x_0}\),\(w_y = \frac{y - y_0}{y_1 - y_0}\)。
- 特点:
- 比最近邻插值更平滑,结果更自然。
- 计算复杂度适中,广泛用于图像缩放。
- 应用:
- 图像放大/缩小(如 OpenCV 的
cv2.resize
)。 - 纹理映射(如 3D 渲染)。
1
2# 双线性插值(放大 2 倍)
bilinear = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR)
- 图像放大/缩小(如 OpenCV 的
特征选择与特征提取
特征选择与特征提取概述
特征选择 (Feature Selection)
- 定义: 从原始特征集合中选择一个子集,保留最相关、最具区分度的特征,去除冗余或无关特征。
- 目标: 降低维度、减少计算量、避免过拟合、提高模型可解释性。
- 方法分类:
- 过滤法 (Filter Methods): 基于统计指标(如方差、相关系数)选择特征,独立于模型。
- 包装法 (Wrapper Methods): 通过模型性能(如交叉验证)评估特征子集。
- 嵌入法 (Embedded Methods): 在模型训练过程中进行特征选择(如 LASSO 回归)。
- 优点: 保留原始特征的物理意义,计算效率较高。
- 缺点: 可能忽略特征之间的复杂关系。
特征提取 (Feature Extraction)
- 定义: 将原始高维数据通过变换(如线性或非线性映射)转换为新的低维特征空间,生成新的特征表示。
- 目标: 提取更有代表性的特征,捕捉数据中的关键模式或结构。
- 方法分类:
- 线性方法: 如主成分分析 (PCA)、线性判别分析 (LDA)。
- 非线性方法: 如 t-SNE、核 PCA、深度学习特征提取。
- 优点: 能捕捉复杂模式,适用于高维数据。
- 缺点: 新特征可能丧失物理意义,计算复杂度较高。
差异
- 输入输出: 特征选择从原始特征中挑选子集,输出是原始特征的子集;特征提取生成新的特征表示。
- 计算复杂度: 特征选择通常比特征提取简单。
- 应用场景: 特征选择适合解释性要求高的场景;特征提取适合高维数据或需要捕捉复杂模式的场景。
特征选择与特征提取原理
特征选择原理
特征选择的目的是从原始特征集合中挑选一个子集,保留最具区分度、最相关的特征,减少冗余和噪声。以下是其核心原理和数学基础:
目标: 最大化模型性能(如分类精度),最小化特征数量以降低计算复杂度和过拟合风险。
数学表示: - 给定特征集 \(X = \{x_1, x_2, \dots, x_n\}\)(每个 \(x_i\) 是特征向量),目标是选择子集\(S\subseteq \{1, 2, \dots, n\}\),使得目标函数 \(J(S)\)(如分类准确率)最大化: \[ S^* = \arg\max_{S} J(S), \quad \text{s.t.} \ |S| \leq k \] 其中 \(k\) 是期望的特征数量。
方法分类: - 过滤法 (Filter Methods): 使用统计指标(如方差、相关系数、互信息)评估特征的重要性,独立于模型。例如,方差阈值方法移除方差低于某一值的特征: \[ \text{Var}(x_i) = \frac{1}{m} \sum_{j=1}^m (x_{i,j} - \mu_i)^2 \] 其中 \(\mu_i\)是特征 \(x_i\)的均值,\(m\)是样本数。 - 包装法 (Wrapper Methods): 通过模型性能(如交叉验证得分)迭代评估特征子集。例如,递归特征消除 (RFE) 通过模型权重或重要性排序特征,逐步移除不重要特征。 - 嵌入法 (Embedded Methods): 在模型训练过程中进行特征选择。例如,L1 正则化 (LASSO) 通过惩罚项使不重要特征的权重趋于零: \[ \min_w \left( \frac{1}{m} \sum_{i=1}^m (y_i - w^T x_i)^2 + \lambda \|w\|_1 \right) \] 其中 \(\lambda\)控制正则化强度。
特征提取原理
特征提取通过变换将原始高维数据映射到低维空间,生成新的特征表示,捕捉数据的关键模式。
- 目标: 提取更具代表性的特征,降低维度,同时保留或增强数据区分能力。
- 数学表示:
- 给定数据矩阵 \(X \in \mathbb{R}^{m \times n}\)(\(m\) 个样本,\(n\) 个特征),特征提取寻找变换函数 \(f: \mathbb{R}^n \to \mathbb{R}^k\)(\(k < n\)),使得新特征 \(Z = f(X)\) 更适合后续任务。
- 线性方法(如 PCA)通过矩阵分解或投影实现: \[ Z = X \cdot W \] 其中 \(W \in \mathbb{R}^{n \times k}\) 是变换矩阵。
- 非线性方法(如 t-SNE)通过优化复杂目标函数(如 KL 散度)实现降维。
- 方法分类:
- 线性方法: 主成分分析 (PCA)、线性判别分析 (LDA)。
- 非线性方法: t-SNE、核 PCA、深度学习特征提取。
- 局部特征提取: 如 SIFT、ORB、HOG,专注于图像局部不变特征。
扩展的特征选择方法及代码
以下介绍三种特征选择方法:方差阈值(过滤法)、递归特征消除 (RFE, 包装法)、L1 正则化 (嵌入法)。
方差阈值(过滤法)
- 原理: 移除方差低于阈值的特征,因为低方差特征变化小,区分能力弱。
- 数学: 计算每个特征的方差,选择方差大于阈值 \(\theta\) 的特征: \[ \text{Var}(x_i) \geq \theta \]
1 | import cv2 |
说明: 代码将图像像素作为特征,使用 VarianceThreshold
移除方差低于 10 的特征。
递归特征消除 (RFE, 包装法)
- 原理: 使用模型(如 SVM)评估特征重要性,递归移除最不重要的特征,直到达到指定数量。
- 数学: 对于模型权重 \(w\),特征重要性基于 \(|w_i|\),移除最小值后重新训练。
1 | import cv2 |
说明: 代码提取图像均值、标准差、最大值作为特征,使用 RFE 选择 2 个最重要特征。需更多样本和标签以实际应用。
L1 正则化(嵌入法)
- 原理: 通过 L1 正则化(如 LASSO)使不重要特征的权重趋于零,自动选择特征。
- 数学: 优化目标: \[ \min_w \left( \frac{1}{m} \sum_{i=1}^m (y_i - w^T x_i)^2 + \lambda \|w\|_1 \right) \]
1 | import cv2 |
说明: 代码使用 LASSO 回归选择特征,非零权重的特征被选中。
扩展的特征提取方法及代码
以下介绍五种特征提取方法:主成分分析 (PCA)、线性判别分析 (LDA)、SIFT、ORB 和 HOG。
主成分分析 (PCA)
- 原理: 通过协方差矩阵的特征分解,将数据投影到方差最大的方向,降低维度,无监督。
- 数学:
- 标准化数据:\(X_{\text{norm}} = (X - \mu)/\sigma\)。
- 计算协方差矩阵:\(C = \frac{1}{m} X_{\text{norm}}^T X_{\text{norm}}\)。
- 特征分解:\(C = W \Lambda W^T\),选择前 \(k\) 个特征向量 \(W_k\)。
- 投影:\(Z = X_{\text{norm}} \cdot W_k\).
1 | import cv2 |
说明: 代码将图像像素降维到 2 维并重构,展示 PCA 效果。
线性判别分析 (LDA)
- 原理: 最大化类间方差、最小化类内方差,适用于监督学习,一般需要多张图片,因为单一张图片标签难以提取。
- 数学:
- 计算类内散布矩阵 \(S_W\) 和类间散布矩阵 \(S_B\): \[ S_W = \sum_{c} \sum_{i \in c} (x_i - \mu_c)(x_i - \mu_c)^T, \quad S_B = \sum_{c} n_c (\mu_c - \mu)(\mu_c - \mu)^T \]
- 求解广义特征值问题:\(S_W^{-1} S_B w = \lambda w\),取前 \(k\) 个特征向量。
1 | import cv2 |
说明: 代码模拟两张图像(需 image1.jpg
和 image2.jpg
),使用 LDA 降维到 1 维。实际应用需更多样本。
SIFT 特征提取
基本概念
- 目标:检测图像中的关键点(角点等),并为每个关键点生成描述子,用于图像匹配、目标识别等任务。
- 特性:
- 尺度不变:通过尺度空间检测,适应不同大小的目标。
- 旋转不变:通过分配主方向,描述子相对于方向归一化。
- 光照鲁棒:基于梯度信息,对亮度变化不敏感。
- 应用:图像匹配、物体识别、3D重建。
SIFT算法步骤
- 尺度空间极值检测:
- 构建高斯金字塔(不同尺度和模糊程度的图像)。
- 计算相邻尺度的高斯差分(DoG,Difference of Gaussian): \[D(x, y, \sigma) = L(x, y, k\sigma) - L(x, y, \sigma) \]其中\(L(x, y, \sigma) = G(x, y, \sigma) * I(x, y)\)是高斯模糊图像。其实本质是求二次偏导,其函数形式与DoG十分类似,故使用DoG函数。
- 在DoG中寻找局部极值点(3D空间:x, y, 尺度)。
- 关键点定位:
- 过滤低对比度或边缘点,确保关键点稳定。
- 使用泰勒展开精确定位极值点。
- 方向分配:
- 计算关键点邻域的梯度方向直方图,分配主方向(峰值方向)。
- 使描述子对旋转不变。
- 描述子生成:
- 在关键点周围取16x16邻域,分成4x4子块。
- 每个子块计算8个方向的梯度直方图,生成128维描述子(4x4x8=128)。
1 | import cv2 |
说明: 代码提取 SIFT 关键点和描述子,需 opencv-contrib-python
。
ORB 特征提取
- 原理: 方向快速和旋转 BRIEF (ORB) 是一种高效的局部特征检测算法,结合 FAST 关键点检测和 BRIEF 描述子,速度快且对旋转鲁棒。但是对尺度的检测并不十分敏感。算法主要是求速度。
- 步骤:
- FAST 检测关键点。
- 计算关键点方向。
- 生成 BRIEF 描述子。
1 | import cv2 |
说明: 代码使用 ORB 检测关键点,速度比 SIFT 快,适合实时应用。
HOG 特征提取
- 原理: 方向梯度直方图 (HOG) 通过计算图像局部区域的梯度方向直方图,生成特征描述子,常用于行人检测。
- 步骤:
- 计算图像梯度(x 和 y 方向)。
- 将图像分成小单元 (cell,一般8×8),计算每个单元的梯度方向直方图。
- 将单元组成块 (block,一般2×2cell),归一化直方图。
- 连接所有块的特征向量。
1 | import cv2 |
说明: 代码使用 skimage.feature.hog
计算 HOG 特征,需安装 scikit-image
(pip install scikit-image
)。
总结
- 特征选择:
- 方差阈值: 简单高效,适合高维数据筛选。
- RFE: 结合模型性能,精准但计算成本高。
- L1 正则化: 自动选择特征,适合回归任务。
- 特征提取:
- PCA: 线性降维,适合图像压缩。
- LDA: 监督降维,适合分类任务。
- SIFT: 尺度不变特征,适合图像匹配。
- ORB: 高效局部特征,适合实时应用。
- HOG: 梯度方向特征,适合行人检测。
- 除此之外还有SURF(基于SIFT的快速算法)、LBP(人脸识别)等 [[../TrDentityCo.png]]
- OpenCV 应用:
- 特征选择常结合
sklearn
,特征提取可直接使用 OpenCV 的 SIFT、ORB 或外部库的 HOG。 - 这些方法在图像分类、目标检测、图像检索中广泛应用。
- 特征选择常结合
边缘提取
边缘提取是计算机视觉的基础任务,用于检测图像中亮度或颜色发生显著变化的区域,通常对应于物体的边界。本文记录以下常用方法Canny、Roberts、Sobel、Prewitt、Hessian特征、Haar特征、Laplacian和Scharr。
1. Canny 边缘检测
原理
Canny 边缘检测是一种多阶段算法,旨在检测强边缘并抑制噪声。它包括以下步骤: 1. 噪声抑制:使用高斯模糊平滑图像,减少噪声影响。 2. 梯度计算:使用 Sobel 算子计算图像的强度梯度和方向。 3. 非极大值抑制:在梯度方向上,仅保留局部最大值,抑制非边缘点。 4. 双阈值检测:使用高低阈值将边缘分为强边缘、弱边缘和非边缘。 5. 边缘跟踪:通过连通性分析,将弱边缘与强边缘连接,剔除孤立点。
优缺点
- 优点:
- 检测精度高,边缘定位准确。
- 能有效抑制噪声,减少误检。
- 提供连通性强的边缘。
- 缺点:
- 计算复杂度较高,实时性较差。
- 对阈值选择敏感,需手动调整。
- 对复杂背景的边缘检测可能不理想。
适用条件
- 适用于需要高质量边缘检测的场景,如图像分割、物体检测。
- 适合噪声较少的图像,或经过预处理的图像。
Python + OpenCV 代码
1 | # Canny 边缘检测 |
2. Roberts 边缘检测
原理
Roberts 算子是一种简单的边缘检测方法,使用 2x2 的卷积核计算图像的梯度。它通过以下两个核检测对角方向的边缘: - \(G_x = \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}\) - \(G_y = \begin{bmatrix} 0 & 1 \\ -1 & 0 \end{bmatrix}\)
梯度幅值计算为:\(G = \sqrt{G_x^2 + G_y^2}\)。
优缺点
- 优点:
- 计算简单,速度快。
- 对对角边缘敏感。
- 缺点:
- 对噪声非常敏感,容易产生伪边缘。
- 仅检测对角方向边缘,对水平和垂直边缘效果较差。
- 边缘定位不精确。
适用条件
- 适用于噪声极低的简单图像。
- 适合对计算速度要求高的实时应用。
Python + OpenCV 代码
1 | # 定义 Roberts 算子 |
3. Sobel 边缘检测
原理
Sobel 算子通过 3x3 的卷积核计算图像在水平和垂直方向的梯度,强调边缘区域。它使用以下核: - \(G_x = \begin{bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{bmatrix}\) - \(G_y = \begin{bmatrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1 \end{bmatrix}\)
梯度幅值为:\(G = \sqrt{G_x^2 + G_y^2}\),方向为:\(\theta = \arctan(G_y / G_x)\)。
优缺点
- 优点:
- 对水平和垂直边缘检测效果较好。
- 计算简单,适合实时处理。
- 比 Roberts 更抗噪。
- 缺点:
- 对对角边缘检测较弱。
- 边缘可能较粗糙,定位不够精确。
- 对高噪声图像效果较差。
适用条件
- 适用于检测水平和垂直边缘的场景,如道路线检测。
- 适合噪声适中的图像。
Python + OpenCV 代码
1 | # Sobel 边缘检测 |
4. Prewitt 边缘检测
原理
Prewitt 算子与 Sobel 类似,也是 3x3 卷积核,用于计算水平和垂直方向的梯度,但权重更均匀: - \(G_x = \begin{bmatrix} -1 & 0 & 1 \\ -1 & 0 & 1 \\ -1 & 0 & 1 \end{bmatrix}\) - \(G_y = \begin{bmatrix} -1 & -1 & -1 \\ 0 & 0 & 0 \\ 1 & 1 & 1 \end{bmatrix}\)
梯度幅值和方向计算同 Sobel。
优缺点
- 优点:
- 计算简单,速度快。
- 对水平和垂直边缘有较好响应。
- 缺点:
- 比 Sobel 更易受噪声影响。
- 边缘定位精度较低。
- 对复杂纹理图像效果较差。
适用条件
- 适用于简单图像的边缘检测。
- 适合对噪声要求不高的场景。
Python + OpenCV 代码
1 | # 定义 Prewitt 算子 |
5. Hessian 特征
原理
Hessian 特征基于图像的二阶导数,通过 Hessian 矩阵检测图像中的显著点(如角点或边缘)。Hessian 矩阵定义为: \[ H = \begin{bmatrix} I_{xx} & I_{xy} \\ I_{xy} & I_{yy} \end{bmatrix} \] 其中 \(I_{xx}, I_{xy}, I_{yy}\) 是图像的二阶偏导数。特征点通过矩阵的行列式或特征值分析确定。
在边缘检测中,Hessian 常用于检测细长结构(如血管),通过分析行列式 \(\det(H)\) 或特征值。
优缺点
- 优点:
- 对细长边缘或线状结构检测效果好。
- 能捕捉图像的局部几何特征。
- 缺点:
- 计算复杂度高,需计算二阶导数。
- 对噪声敏感,需预处理。
- 不适合检测宽边缘或复杂纹理。
适用条件
- 适用于医疗图像(如血管分割)或线状结构检测。
- 适合噪声较低或经过平滑处理的图像。
Python + OpenCV 代码
1 | import cv2 |
6. Haar 特征
原理
Haar 特征主要用于目标检测(如人脸检测),通过计算矩形区域的像素强度差值提取特征。Haar 特征包括: - 边缘特征:检测水平或垂直边缘。 - 线特征:检测线状结构。 - 中心-环绕特征:检测中心与周围的差异。
特征值计算为:白色区域像素和减去黑色区域像素和。Haar 特征通常结合积分图像加速计算。
优缺点
- 优点:
- 计算速度快,适合实时应用。
- 对简单边缘和纹理特征有效。
- 缺点:
- 对复杂边缘或非矩形特征检测效果差。
- 对光照变化和旋转敏感。
- 需大量训练数据(如用于人脸检测)。
适用条件
- 适用于目标检测(如人脸、车辆)。
- 适合光照均匀、目标形状规则的场景。
Python + OpenCV 代码
1 | import cv2 |
7. Laplacian 边缘检测
原理
Laplacian 算子基于图像的二阶导数,检测亮度变化的区域。它使用以下核: \[ \nabla^2 I = \begin{bmatrix} 0 & 1 & 0 \\ 1 & -4 & 1 \\ 0 & 1 & 0 \end{bmatrix} \]
Laplacian 检测零交叉点作为边缘。
优缺点
- 优点:
- 对所有方向的边缘敏感。
- 计算简单。
- 缺点:
- 极易受噪声影响,需预平滑。
- 边缘可能不连续,需后处理。
适用条件
- 适用于噪声低的图像。
- 适合与高斯平滑结合使用。
Python + OpenCV 代码
1 | import cv2 |
8. Scharr 边缘检测
原理
Scharr 算子是 Sobel 的改进版,使用更精确的权重来计算梯度: - \(G_x = \begin{bmatrix} -3 & 0 & 3 \\ -10 & 0 & 10 \\ -3 & 0 & 3 \end{bmatrix}\) - \(G_y = \begin{bmatrix} -3 & -10 & -3 \\ 0 & 0 & 0 \\ 3 & 10 & 3 \end{bmatrix}\)
优缺点
- 优点:
- 比 Sobel 更精确,边缘定位更好。
- 计算速度与 Sobel 相近。
- 缺点:
- 对噪声仍较敏感。
- 对复杂纹理效果有限。
适用条件
- 适用于需要高精度边缘检测的场景。
- 适合噪声适中的图像。
Python + OpenCV 代码
1 | import cv2 |
相机模型
相机模型描述了三维世界如何通过相机投影到二维图像平面。以下是对你列出的内容(小孔成像模型、相机模型、镜头畸变、透视变换)以及补充内容(鱼眼模型、立体视觉)的详细讲解。
1. 小孔成像模型
原理
小孔成像模型是相机成像的理想化模型,假设光线通过一个无穷小的孔(针孔)投影到成像平面,无透镜畸变。数学表达为: \[ \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = \frac{f}{Z} \begin{bmatrix} X \\ Y \\ Z \end{bmatrix} \] 其中: - \((X, Y, Z)\):世界坐标。 - \((u, v)\):图像坐标。 - \(f\):焦距。 - \(Z\):物体到针孔的深度。
优缺点
- 优点:
- 模型简单,易于理解和计算。
- 无畸变,适合理论分析。
- 缺点:
- 针孔会导致光量不足,实际相机需透镜。
- 不考虑畸变,无法描述真实相机。
适用条件
- 适用于教学和简单几何分析。
- 不适合需要高精度建模的实际应用。
Python + OpenCV 代码
1 | # 模拟小孔成像 |
2. 相机模型(针孔相机模型+内参外参)
原理
相机模型是对小孔成像的扩展,考虑内参(焦距、 principal point)和外参(旋转、平移)。投影公式为: \[ \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = K [R | t] \begin{bmatrix} X \\ Y \\ Z \\ 1 \end{bmatrix} \] 其中: - \(K = \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix}\):内参矩阵,\(f_x, f_y\) 为焦距,\(c_x, c_y\) 为 principal point。 - \([R | t]\):外参矩阵,\(R\) 为旋转矩阵,\(t\) 为平移向量。
优缺点
- 优点:
- 能精确描述相机成像过程。
- 支持 3D 重建和姿态估计。
- 缺点:
- 不考虑镜头畸变,需额外校正。
- 标定过程复杂。
适用条件
- 适用于 3D 重建、SLAM、增强现实。
- 适合需要精确几何关系的场景。
Python + OpenCV 代码
1 | # 定义内参矩阵 |
3. 镜头畸变
原理
镜头畸变是由于透镜非理想性导致的图像失真,主要包括: - 径向畸变:靠近图像中心的点移向边缘(桶形畸变)或反之(枕形畸变)。模型为: \[ x_d = x (1 + k_1 r^2 + k_2 r^4 + k_3 r^6) \] \[ y_d = y (1 + k_1 r^2 + k_2 r^4 + k_3 r^6) \] 其中 \(r = \sqrt{x^2 + y^2}\),\(k_1, k_2, k_3\) 为径向畸变系数。 - 切向畸变:由于透镜与传感器不完全平行,模型为: \[ x_d = x + [2 p_1 x y + p_2 (r^2 + 2 x^2)] \] \[ y_d = y + [p_1 (r^2 + 2 y^2) + 2 p_2 x y] \]
优缺点
- 优点:
- 校正畸变后可获得更精确的几何关系。
- 适用于广角镜头或鱼眼镜头。
- 缺点:
- 标定过程复杂,需棋盘格或其他标定物。
- 校正可能导致图像部分区域丢失。
适用条件
- 适用于广角镜头或高精度成像系统。
- 适合需要校正畸变的场景,如 3D 重建、SLAM。
Python + OpenCV 代码
1 | # 定义内参和畸变系数(需通过标定获得) |
4. 透视变换
原理
透视变换将图像从一个视角变换到另一个视角,基于单应性矩阵(Homography)。变换公式为: \[ \begin{bmatrix} u' \\ v' \\ 1 \end{bmatrix} = H \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} \] 其中 \(H\) 是一个 3x3 矩阵,通过至少 4 对对应点计算。
优缺点
- 优点:
- 能实现图像的视角变换,适用于校正倾斜或拼接。
- 计算简单,效果直观。
- 缺点:
- 要求平面场景,非平面场景会失效。
- 对对应点精度要求高。
适用条件
- 适用于图像拼接、文档校正、增强现实。
- 适合平面对象的视角变换。
Python + OpenCV 代码
1 | import cv2 |
5. 鱼眼模型
原理
鱼眼镜头具有超广角,导致严重畸变。鱼眼模型通常使用等距投影或其他非线性投影,校正公式为: \[ r_d = f \theta \] 其中 \(\theta = \arctan(r_u / f)\),\(r_d\) 和 \(r_u\) 分别为畸变和未畸变半径。
优缺点
- 优点:
- 能捕获超广角视野,适合全景成像。
- 校正后可用于 3D 重建。
- 缺点:
- 畸变严重,校正复杂。
- 边缘分辨率较低。
适用条件
- 适用于全景相机或监控系统。
- 适合需要超广角的场景。
Python + OpenCV 代码
1 | # 读取鱼眼图像 |
6. 立体视觉
原理
立体视觉通过两台相机的视差计算场景深度。基本公式为: \[ Z = \frac{f T}{d} \] 其中: - \(Z\):深度。 - \(f\):焦距。 - \(T\):两相机基线距离。 - \(d\):视差(左图和右图对应点的水平偏移)。
优缺点
- 优点:
- 能直接计算 3D 深度信息。
- 适用于机器人导航、3D 重建。
- 缺点:
- 对相机标定和匹配精度要求高。
- 计算复杂度高,实时性较差。
适用条件
- 适用于需要深度信息的场景,如自动驾驶、机器人。
- 适合纹理丰富的场景。
Python + OpenCV 代码
1 | img_left = cv2.imread('left_image.jpg', cv2.IMREAD_GRAYSCALE) |
总结
边缘提取算法对比
算法 | 抗噪性 | 边缘定位 | 计算复杂度 | 适用场景 |
---|---|---|---|---|
Canny | 高 | 高 | 中 | 高质量边缘检测 |
Roberts | 低 | 低 | 低 | 简单图像 |
Sobel | 中 | 中 | 低 | 水平/垂直边缘 |
Prewitt | 低 | 低 | 低 | 简单图像 |
Hessian | 低 | 高 | 高 | 线状结构 |
Haar | 中 | 低 | 低 | 目标检测 |
Laplacian | 低 | 中 | 低 | 简单图像 |
Scharr | 中 | 高 | 低 | 高精度边缘 |
相机模型要点
- 小孔成像:理想模型,简单但不实用。
- 相机模型:考虑内参外参,适合精确建模。
- 镜头畸变:校正非理想透镜,广角镜头必备。
- 透视变换:平面视角变换,适合校正和拼接。
- 鱼眼模型:超广角成像,需复杂校正。
- 立体视觉:深度计算,适合 3D 重建。