2. 基于加速度计数据的旋转补偿

任务说明

在EIS电子防抖中,当设备发生旋转运动时,即使平移抖动已被补偿,画面仍会因旋转而出现模糊。本案例利用加速度计输出的三轴加速度数据,估计设备在俯仰(Pitch)与横滚(Roll)方向上的旋转角度,并据此对图像帧进行反向旋转补偿,以消除旋转造成的画面偏移。

实现方案

核心思路:加速度计在静止或缓慢运动时可视为测量重力矢量。当设备倾斜时,重力在三个轴上的分量发生变化,通过反正切运算即可解算出设备相对水平面的倾斜角(即旋转角)。本案例实现以下功能:

  1. 读取加速度计三轴原始数据(单位:g);
  2. 计算Pitch角:pitch = atan2(-acc_x, sqrt(acc_y² + acc_z²));
  3. 计算Roll角:roll = atan2(acc_y, acc_z);
  4. 将角度转换为像素偏移量,对输入图像进行仿射逆变换补偿。

代码实现

import numpy as np
import cv2

def accel_to_rotation(acc_x, acc_y, acc_z):
    """
    由加速度计数据计算旋转角(弧度)
    输入:三轴加速度值,单位g(重力加速度)
    返回:pitch, roll(弧度)
    """
    # 防止除零
    denom = np.sqrt(acc_y**2 + acc_z**2)
    if denom < 1e-6:
        denom = 1e-6
    pitch = np.arctan2(-acc_x, denom)
    roll = np.arctan2(acc_y, acc_z)
    return pitch, roll

def rotation_compensate(image, pitch, roll, focal_length=500):
    """
    根据旋转角对图像进行反向补偿
    image: 输入灰度或BGR图像
    pitch, roll: 弧度制旋转角
    focal_length: 相机焦距(像素),用于将角度映射为像素位移
    """
    h, w = image.shape[:2]
    # 角度转像素位移(小角度近似:位移 ≈ 焦距 × 角度)
    dx = focal_length * roll
    dy = focal_length * pitch
    # 构造平移矩阵(反向补偿)
    M = np.float32([[1, 0, -dx],
                    [0, 1, -dy]])
    compensated = cv2.warpAffine(image, M, (w, h),
                                 flags=cv2.INTER_LINEAR,
                                 borderMode=cv2.BORDER_REPLICATE)
    return compensated

# ===== 样例输入与调用 =====
if __name__ == "__main__":
    # 模拟加速度计读数:设备绕X轴倾斜10°,绕Y轴倾斜5°
    # 重力矢量在设备坐标系中的投影(单位g)
    acc_x = 0.1736   # ≈ sin(10°)
    acc_y = 0.0872   # ≈ sin(5°)
    acc_z = 0.9848   # ≈ cos(10°)*cos(5°)

    pitch, roll = accel_to_rotation(acc_x, acc_y, acc_z)
    print(f"Pitch: {np.degrees(pitch):.2f}°, Roll: {np.degrees(roll):.2f}°")

    # 生成测试图像(黑色背景上的白色矩形)
    img = np.zeros((300, 400), dtype=np.uint8)
    cv2.rectangle(img, (100, 80), (250, 200), 255, -1)

    # 执行旋转补偿
    result = rotation_compensate(img, pitch, roll)

    # 保存结果供人工检查
    cv2.imwrite("compensated.png", result)
    print("补偿图像已保存为 compensated.png")

关键逻辑说明

上述代码中,accel_to_rotation函数利用重力矢量投影关系解算设备姿态角。当设备水平放置时,acc_z≈1g,acc_x≈acc_y≈0,此时pitch和roll均为0;当设备倾斜时,对应轴出现重力分量,角度随之变化。rotation_compensate函数将角度乘以焦距转换为像素位移,并通过仿射平移矩阵实现反向补偿——即图像向旋转的反方向移动,抵消旋转造成的画面偏移。

验证方法

运行方式:在Python环境中安装numpy和opencv-python后直接运行脚本。

判定标准:

  1. 控制台输出的Pitch角应接近10°,Roll角应接近5°(误差在0.1°以内);
  2. 打开生成的compensated.png,观察白色矩形相对原始位置发生了向上和向左的位移(因为pitch为正时dy为正,图像上移;roll为正时dx为正,图像左移),位移量约为500×tan(10°)≈88像素(垂直)和500×tan(5°)≈44像素(水平);
  3. 若将acc_x和acc_y设为0,则输出角度为0,补偿图像与原始图像完全一致。
加速度计旋转补偿流程 加速度计数据 (acc_x, acc_y, acc_z) 姿态解算 atan2 → pitch, roll 角度→像素位移 dx=f·roll, dy=f·pitch 补偿 设备坐标系 X Y Z g pitch 补偿效果(俯视) 原始 补偿后 反向位移 补偿方向与旋转方向相反,抵消画面偏移

边界与限制

本实现基于小角度近似,适用于旋转角小于15°的场景(此时误差小于1%)。当设备存在显著线性加速度时(如剧烈运动),加速度计测得值将包含运动加速度分量,导致角度估计偏差,此时需结合陀螺仪数据(见后续案例)。本案例仅演示旋转补偿核心算法,未包含完整EIS流水线中的平移补偿与边缘裁剪处理。