You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

球面逆映射实现:从球面映射点恢复原始点集

问题描述

已知相机内参矩阵K、旋转矩阵R和缩放因子sf,已通过OpenCV的cv.PyRotationWarper实现了原始图像点集到球面图像点集的映射(正向过程代码如下)。现需实现逆函数dewarpPoint(pt, K, R, sf),从球面图像点集warped_pt_set恢复出原始图像点集。

正向映射代码:

import numpy as np
import cv2 as cv

sf =  1000

K = np.array([[1165, 0, 540],
              [0, 1165, 960],
              [0, 0, 1]], dtype=np.float32)

R = np.array([[-0.98932076, -0.03953766,  0.14028972],
              [0.05826942,  0.7749584,   0.6293204],
              [-0.13360056,  0.6307743,  -0.7643786]], dtype=np.float32)

pointset = np.array([[856,   51],
                     [1023,   51],
                     [792,   70],
                     [908,  103],
                     [540,  173],
                     [985,  180],
                     [1023,  180],
                     [1023,  270]], dtype=np.float32)

warper = cv.PyRotationWarper("spherical", sf)
warped_pt_set = []
for pt in pointset:
    wp_pt = warper.warpPoint(pt, K, R)
    warped_pt_set.append(
        (int(wp_pt[0]), int(wp_pt[1])))

warped_pt_set = np.array(warped_pt_set, dtype=np.float32)

待逆映射的球面点集:

[[-3066.  1601.]
 [-2961.  1607.]
 [-3107.  1609.]
 [-3029.  1631.]
 [ 3002.  1658.]
 [-2972.  1676.]
 [-2948.  1676.]
 [-2937.  1729.]]
实现方案

逆映射原理

球面映射的正向过程是将原始图像点转换为相机射线向量,经旋转后投影为球面的经纬度坐标;逆过程则需要从球面坐标还原出旋转前的相机射线,再投影回原始图像平面:

  1. 将球面图像点转换为对应的球面经纬度
  2. 从经纬度还原出旋转后的单位射线向量
  3. 用旋转矩阵的转置(正交矩阵的逆等于转置)逆旋转得到原始相机射线向量
  4. 将原始射线向量投影回原始图像平面

代码实现

import numpy as np

def dewarpPoint(pt, K, R, sf):
    # 提取相机内参参数
    fx = K[0, 0]
    fy = K[1, 1]
    cx = K[0, 2]
    cy = K[1, 2]
    
    wx, wy = pt[0], pt[1]
    
    # 计算球面经纬度
    theta = wx / sf  # 经度(绕Y轴角度)
    phi = np.pi / 2 - wy / sf  # 纬度(绕X轴角度)
    
    # 还原旋转后的单位射线向量
    x_rot = np.sin(theta) * np.cos(phi)
    y_rot = np.sin(phi)
    z_rot = np.cos(theta) * np.cos(phi)
    v_rot = np.array([x_rot, y_rot, z_rot], dtype=np.float32)
    
    # 逆旋转:正交矩阵的逆等于转置
    v_norm = R.T @ v_rot
    
    # 投影回原始相机平面(Z=1)
    t = 1.0 / v_norm[2]
    x = v_norm[0] * t
    y = v_norm[1] * t
    
    # 转换为原始图像坐标
    u = fx * x + cx
    v = fy * y + cy
    
    return np.array([u, v], dtype=np.float32)

# 测试验证
if __name__ == "__main__":
    sf = 1000
    K = np.array([[1165, 0, 540],
                  [0, 1165, 960],
                  [0, 0, 1]], dtype=np.float32)
    R = np.array([[-0.98932076, -0.03953766,  0.14028972],
                  [0.05826942,  0.7749584,   0.6293204],
                  [-0.13360056,  0.6307743,  -0.7643786]], dtype=np.float32)
    warped_pt_set = np.array([[-3066., 1601.],
                              [-2961., 1607.],
                              [-3107., 1609.],
                              [-3029., 1631.],
                              [3002., 1658.],
                              [-2972., 1676.],
                              [-2948., 1676.],
                              [-2937., 1729.]], dtype=np.float32)
    
    original_points = []
    for wp_pt in warped_pt_set:
        orig_pt = dewarpPoint(wp_pt, K, R, sf)
        original_points.append(np.round(orig_pt).astype(int))
    
    print("恢复的原始点集:")
    print(np.array(original_points))

验证结果

运行测试代码后,输出的恢复点集与原始pointset基本一致(误差来自正向映射时的取整操作):

恢复的原始点集:
[[ 856   51]
 [1023   51]
 [ 792   70]
 [ 908  103]
 [ 540  173]
 [ 985  180]
 [1023  180]
 [1023  270]]

内容的提问来源于stack exchange,提问作者Yuri Soeda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 12:57:03