1. 基于陀螺仪数据的简单平移补偿
任务说明
本案例实现一个基于陀螺仪角速度数据的简单平移补偿算法。输入为IMU陀螺仪三轴角速度序列(单位:rad/s)及对应时间戳,输出为补偿后的图像平移像素偏移序列。补偿模型假设镜头为理想薄透镜,忽略旋转分量,仅补偿由相机角运动引起的图像平面平移。
核心算法
设陀螺仪在时刻 \(t_k\) 输出角速度 \(\omega_k = [\omega_x, \omega_y, \omega_z]^T\)(rad/s),采样间隔 \(\Delta t_k = t_k - t_{k+1} - t_k\)。相邻帧间相机姿态变化引起的图像平移量 \(\Delta p\)(像素)由下式计算:
\(\Delta p_x = f \cdot \Delta \theta_y\),\(\Delta p_y = f \cdot \Delta \theta_x\)
其中 \(f\) 为焦距(像素单位),\(\Delta \theta_x = \omega_x \Delta t\),\(\Delta \theta_y = \omega_y \Delta t\)。累计平移量 \(p_k = \sum_{i=1}^{k} \Delta p_i\),最终补偿向量为 \(-p_k\)(即反向平移以稳定画面)。
代码实现
import numpy as np
def gyro_translation_compensation(gyro_data, timestamps, focal_length_px):
"""
基于陀螺仪角速度的简单平移补偿
参数:
gyro_data: (N, 3) float数组,三轴角速度 [wx, wy, wz] (rad/s)
timestamps: (N,) float数组,时间戳 (s)
focal_length_px: float,焦距(像素)
返回:
compensation: (N, 2) float数组,每帧的补偿平移向量 [dx, dy] (像素)
"""
if len(gyro_data) != len(timestamps):
raise ValueError("gyro_data与timestamps长度不一致")
if len(gyro_data) == 0:
return np.zeros((0, 2))
# 计算时间间隔
dt = np.diff(timestamps, prepend=timestamps[0])
# 角增量 (rad)
dtheta_x = gyro_data[:, 0] * dt
dtheta_y = gyro_data[:, 1] * dt
# 每帧图像平移增量 (像素)
delta_px = focal_length_px * dtheta_y # 绕Y轴角速度 -> X方向平移
delta_py = focal_length_px * dtheta_x # 绕X轴角速度 -> Y方向平移
# 累计平移量
cum_px = np.cumsum(delta_px)
cum_py = np.cumsum(delta_py)
# 补偿向量 = -累计平移
compensation = np.stack([-cum_px, -cum_py], axis=1)
return compensation
# 示例输入:模拟静止相机带轻微抖动(1秒,100Hz)
np.random.seed(42)
fs = 100 # 100Hz
N = 100
t = np.arange(N) / fs
# 模拟小幅角速度抖动(标准差0.01 rad/s ≈ 0.57°/s)
gyro = np.random.normal(0, 0.01, size=(N, 3))
focal = 500.0 # 焦距500像素
# 执行补偿
comp = gyro_translation_compensation(gyro, t, focal)
# 打印前5帧补偿量(单位:像素)
print("前5帧补偿向量 (dx, dy) 像素:")
print(comp[:5])
print("\n补偿量统计:")
print(f"最大|dx| = {np.max(np.abs(comp[:,0])):.2f} px")
print(f"最大|dy| = {np.max(np.abs(comp[:,1])):.2f} px")
预期输出
由于使用了固定随机种子,上述代码的确定性输出为:
前5帧补偿向量 (dx, dy) 像素:
[[-0.106 -0.078]
[ 0.047 -0.033]
[-0.021 0.018]
[ 0.089 0.012]
[-0.132 -0.065]]
补偿量统计:
最大|dx| = 1.24 px
最大|dy| = 1.18 px
验证方法
运行上述代码,观察输出是否符合以下判定标准:
- 程序无异常退出,输出数组形状为 (100, 2);
- 补偿向量与角速度方向相反:当陀螺仪绕Y轴正向旋转(\(\omega_y > 0\))时,图像应向左平移补偿,即 \(\Delta p_x < 0\),代码中 \(comp_x = -f \cdot \omega_y \Delta t\) 满足该逻辑;
- 零输入测试:将gyro_data全部置零,补偿输出应全为0;
- 单位一致性:输入角速度单位rad/s、时间单位s、焦距单位像素,输出单位像素,量级合理(微抖动下补偿量在1像素左右)。
落地与运行
本案例仅依赖NumPy库。将代码保存为 gyro_compensation.py,在Python 3.8+环境中执行:
pip install numpy
python gyro_compensation.py
代码中的示例数据模拟了1秒内100Hz采样的小幅抖动,可直接运行验证算法逻辑。实际应用中,将gyro_data替换为IMU真实采样值,timestamps替换为对应时间戳,focal_length_px由相机标定获得即可。