亚像素,其实质在于在像素网格间进行更细致的插值和拟合,使得原本只能精确到整像素的结果,能够细化到像素的小数位。
在常规的图像处理过程中,我们通常使用整数坐标来标识一个像素点,例如,位于第10行第20列的像素点可以表示为(20,10)。这表明:
从数学的角度来看,我们可以假设现实世界的光照强度是一个连续函数 \(f\),其自变量是平面上的坐标 \(x\) 和 \(y\)。因此,图像的采样过程可以被描述为:
\(I[m, n] = f(m\Delta x, n\Delta y)\),其中 \(\Delta x, \Delta y\) 是采样间隔,即每个像素所代表的实际物理距离。
关键点在于,虽然整像素坐标仅记录了离散网格上的数据,但这并不妨碍我们想象网格间的连续变化。
亚像素(Sub-pixel)并不是一种新的像素类型,而是指在计算和估算时,允许坐标、位置、位移等参数采用非整数值,例如12.3像素或0.25像素,通过数学手段估计网格间的连续变化。
例如,若一个特征点的初步定位结果为(100, 50),而通过亚像素技术,我们可以获得更为精确的坐标(100.37, 49.82)。这种技术被称为“亚像素级定位”。
cv2.findChessboardCorners
简单来说,如果在1920×1080分辨率的图像中仅使用整像素坐标来定位一个目标点,最大的定位误差可达±0.5像素。然而,如果我们能实现亚像素级别的精度,比如±0.1像素,那么在许多需要高精度的应用中,性能将显著提升。
当限制坐标为整数像素时,实际上是将真实位置进行了量化。如果真实位置为 \(x^*\),则只能选择 \(\lfloor x^* \rfloor\) 或 \(\lceil x^* \rceil\) 中的一个,这会导致最大量化误差约为0.5像素。亚像素技术则是通过插值或拟合的方式,尽可能恢复 \(x^*\) 的真实值,从而使误差远低于0.5像素。
假设真实场景的亮度分布是一个连续函数 \(f\),而图像是这一连续函数的离散采样:\(I[m, n] = f(m\Delta x, n\Delta y)\)。可以将 \(I[m, n]\) 视作 \(f\) 在点 \((m\Delta x, n\Delta y)\) 上的采样值。对于那些位于采样点之间的位置 \((x, y)\)(非整数索引),可以通过周围几个采样点的值来估算:\(\hat{f}(x, y) \approx \sum_{i,j} w_{ij}(x, y) I[m + i, n + j]\),这里 \(w_{ij}(x, y)\) 表示插值权重,具体取决于所使用的插值方法(如最近邻、双线性、双三次样条等)。这就是亚像素插值的数学基础。
当我们提到“角点坐标为 \((u, v)\),且 \(u, v\) 可以为实数”时,实际上是在执行以下操作:
将u, v视为连续变量;将附近像素的灰度或特征视为某个函数g(u, v)的采样;通过局部优化、拟合、插值找出g(u, v)的极值点,以获得非整数坐标。
例如,在模板匹配过程中,经常需要计算相关系数或误差函数C(u, v),首先在整像素上计算得到C[m, n],然后在最大值附近进行二次曲线拟合,以估算出极值的确切位置(u*, v*),这通常是非整数值。
以下是几种经典且实用的亚像素估计技术:
基本思路是首先构建一个连续的灰度函数f(x, y)(如使用双线性、双三次插值等),然后在这个连续的函数上进行优化。
例如,在光流估计中,目标是找到位移(δx, δy),使以下表达式最小:
E(δx, δy) = ∑(x,y)∈Ω [I2(x+δx, y+δy) - I1(x, y)]2
这里,I2表示后一帧,I1表示前一帧,而(x, y)代表窗口内的像素点。由于x + δx和y + δy通常不是整数,因此需要通过插值来获取I2在任意实数坐标下的值:2(x+δx, y+δy);之后对E进行最小化处理,从而求得实际位移(δx, δy)。这一过程体现了经典的Lucas-Kanade光流算法中的亚像素理念。
常用的插值方法包括:
双线性插值示例(在一个像素网格中):(x, y) = a + bx + cy + dxy,其中a, b, c, d可以通过解决四个邻近像素值的线性方程组来确定。
这种方法在工程实践中非常普遍,因为它结构简单且易于实现。
假设仅在x方向上估计峰值位置。例如,在一维相关匹配中,我们可能得到三个相邻的相关值:左侧C(-1),中间C(0)(整像素匹配的最佳位置),右侧C(1)。假设这三个点大致位于一条二次曲线上:C(x) ≈ ax2 + bx + c。代入上述值并解方程可得a, b, c,但更重要的是求解二次函数的极值点:x* = -b / (2a)。通过代数简化,可以得到一个常用的亚像素估计公式:x* = (1/2) * (C(-1) - C(1)) / (C(-1) - 2C(0) + C(1))。该x*值即为相对于整数位置的亚像素偏移,通常范围在(-1, 1)内。
在二维情况下,可以在x和y方向上分别进行类似的拟合,或者在3x3区域内进行二维二次曲面拟合:C(x, y) ≈ ax2 + by2 + cxy + dx + ey + f,随后求解二元二次函数的极值点(x*, y*)。
此方法常用于细化相关匹配的峰值(如图像配准、模板匹配)以及立体匹配中视差代价曲线的精细化(通过对代价曲线进行抛物线拟合)。
对于某些特定的“峰值”结构(如角点响应函数、亮点中心等),可以采用加权平均的方法来估算中心位置。
公式表示为:
\( x^* = \frac{\sum_i x_i w_i}{\sum_i w_i}, \quad y^* = \frac{\sum_i y_i w_i}{\sum_i w_i} \)
其中,\((x_i, y_i)\) 表示邻域内像素的坐标;\(w_i\) 可以是亮度 \(I[x_i, y_i]\),或某种响应值(例如角点响应值)。此方法相当于将该区域视为一个“质量分布”,并计算其质心。这种方法对于高斯斑点、圆形亮斑等结构非常有效。
在许多亚像素问题中,我们解决的是一个连续优化问题:
\( \min_{\boldsymbol{p}} E(\boldsymbol{p}) \)
例如,\(\boldsymbol{p}\) 可能代表位移、角点偏移量等。如果 \(E\) 在局部近似为二次函数,可以使用泰勒展开近似为:
\( E(\boldsymbol{p}+\Delta\boldsymbol{p}) \approx E(\boldsymbol{p}) + \nabla E(\boldsymbol{p})^\top \Delta\boldsymbol{p} + \frac{1}{2}\Delta\boldsymbol{p}^\top H(\boldsymbol{p}) \Delta\boldsymbol{p} \)
通过对 \(\Delta\boldsymbol{p}\) 的导数设为零,可以得出牛顿步长:
\( \Delta\boldsymbol{p} = - H(\boldsymbol{p})^{-1} \nabla E(\boldsymbol{p}) \)
然后进行迭代更新:
\( \boldsymbol{p} \leftarrow \boldsymbol{p} + \Delta\boldsymbol{p} \)
在图像处理中,\(\nabla E\) 和 \(H\) 均与图像梯度(偏导数)有关,因此这类方法通常要求:
Lucas-Kanade 光流算法、亚像素角点精化都是这一思路的具体应用。
频域/相位相关(Phase Correlation)是一种用于图像平移配准的方法,主要利用傅里叶变换和相移定理。假设两个图像 \(f\) 和 \(g\) 之间存在平移关系:
\( g(x, y) = f(x - \Delta x, y - \Delta y) \)
则在频域中,它们的关系可以表示为:
\( G(u, v) = F(u, v) e^{-j(2\pi u \Delta x / M + 2\pi v \Delta y / N)} \)
通过计算归一化的交叉功率谱:
\( R(u, v) = \frac{F(u, v) \overline{G(u, v)}}{|F(u, v) \overline{G(u, v)}|} \)
再对 \(R(u, v)\) 进行逆傅里叶变换,可以在空间域中得到一个“峰值”,该峰值的位置即为位移 \((\Delta x, \Delta y)\)。
为了实现亚像素精度,可以采取以下措施:
以下是几种常见的亚像素相关操作实例(以 OpenCV 为例):
典型流程包括:
cv2.findChessboardCorners 所示)。cv2.cornerSubPix 对角点位置进行亚像素级别的精细化。以下是一个简化的 Python 伪代码示例:
import cv2
import numpy as np
img = cv2.imread('chessboard.jpg', cv2.IMREAD_GRAYSCALE)
# 1. 初步定位角点(整像素)
ret, corners = cv2.findChessboardCorners(img, patternSize=(9, 6))
# 2. 亚像素精细化
在OpenCV中,为了实现角点坐标的亚像素级优化,可以通过以下代码来设置参数和执行优化过程:
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-3)
corners_subpix = cv2.cornerSubPix(img, corners, winSize=(5, 5), zeroZone=(-1, -1), criteria=criteria)
print(corners_subpix[:5]) # 输出前五个角点的(x, y)浮点数坐标
cornerSubPix
该过程内部实现了基于梯度和局部拟合的亚像素优化。
OpenCV提供的函数能够自动采用亚像素插值技术来计算光流位移,确保返回的点坐标达到浮点数精度:
p1, st, err = cv2.calcOpticalFlowPyrLK(img1, img2, p0, None)
# p1 中存储的是亚像素级别的坐标
在实际应用中,可以在调用此函数之前,先利用角点检测方法找出初步的角点,然后通过上述提到的亚像素优化技术进一步精炼这些角点的位置,最后执行光流计算。整个流程都保持了亚像素级别的精度。
cv2.calcOpticalFlowPyrLK
cv2.goodFeaturesToTrack
许多立体匹配算法(例如基于代价体积的方法)首先确定最佳的整数视差 d0,接着对代价函数 C(d) 在 d0-1, d0, d0+1 进行抛物线拟合,以求得亚像素级的视差值 d*,具体公式如下:
d* = d0 + 1/2 * [C(d0-1) - C(d0+1)] / [C(d0-1) - 2C(d0) + C(d0+1)]
这里,C(d) 越小表示匹配越佳(即代价最低)。通过二次曲线拟合技术,即使在离散化的代价曲线上也能“插值”得到真正的最小值点。
虽然亚像素技术能提高精度,但它也带来了额外的计算负担,并且对图像噪声更为敏感,同时对图像质量的要求也更高。因此,在以下情况下特别推荐使用亚像素技术:
然而,对于只需要粗略检测目标大致位置的任务(例如简单的对象检测或分割),亚像素技术的意义并不大。
由于亚像素估计高度依赖于局部灰度变化的形态特征(如是否平滑、是否呈现高斯峰值),因此建议采取适当的平滑措施(如高斯滤波)来减少噪声的影响。但需注意避免过度模糊,以免破坏图像中的梯度信息和结构细节。此外,对于光照不均的场景,应考虑实施归一化或亮度补偿等预处理步骤。
不同的插值方法适用于不同的情境:
可以通过以下几种方式来评估亚像素技术的实际表现:
总之,亚像素精度并非由硬件决定,而是通过软件算法估算得出的结果。
扫码加好友,拉您进群



收藏
