从等距柱状全景图到透视图像的变换失真

问题描述 投票:0回答:1

给定等距柱状全景图(长宽比 2:1,分辨率 4000x2000)、相机的方向、所需的图像形状和 2D FOV,我正在尝试将其转换为透视图像。根据方向向量,透视图像要么看起来正确,要么旋转不正确并扭曲。

enter image description here

看起来错误的方向是具有 x 和 y 分量的方向。我测试过的所有其他方向看起来都是正确的。您知道我的代码的哪一部分导致了这个问题吗?

def calculate_R(orientation, up=cp.array([0, -1, 0])):

    orientation = orientation / cp.linalg.norm(orientation)

    if cp.allclose(orientation, up):
        return cp.array([[1, 0, 0], [0, 0, 1], [0, -1, 0]])

    if cp.allclose(orientation, -up):
        return cp.array([[1, 0, 0], [0, 0, -1], [0, 1, 0]])

    x = cp.cross(up, orientation)
    x = x / cp.linalg.norm(x)

    y = cp.cross(orientation, x)
    y = y / cp.linalg.norm(y)

    R = cp.array([x, y, orientation])

    return R

def rotate_xyz(R, x, y, z):

    xyz = cp.stack((x.ravel(), y.ravel(), z.ravel()))
    x, y, z = cp.matmul(R, xyz).reshape(3, *x.shape)
    
    return x, y, z

def transform_back(pano, orientation, image_shape, fov=[90, 90]):

    orientation = orientation / cp.linalg.norm(orientation)

    fov_x = cp.radians(fov[0])
    fov_y = cp.radians(fov[1]))

    x_max = cp.tan(fov_x / 2)
    y_max = cp.tan(fov_y / 2)

    x = cp.linspace(-x_max, x_max, num=image_shape[1], dtype=cp.float32)
    y = cp.linspace(-y_max, y_max, num=image_shape[0], dtype=cp.float32)
    x, y = cp.meshgrid(x, y)
    z = -cp.ones_like(x)

    R = calculate_R(orientation)

    x, y, z = Panorama.rotate_xyz(R, x, y, z)
    xyz = cp.stack([x, y, z], axis=-1).reshape(-1, 3)

    lon = cp.arctan2(xyz[:, 0], xyz[:, 2])
    lat = cp.arcsin(xyz[:, 1] / cp.linalg.norm(xyz, axis=1))

    u = ((lon + cp.pi) / (2 * cp.pi)) * pano.shape[1]
    v = ((cp.pi / 2 - lat) / cp.pi) * pano.shape[0]

    u = u.reshape(image_shape[0], image_shape[1]).astype(cp.float32)
    v = v.reshape(image_shape[0], image_shape[1]).astype(cp.float32)

    image = cp.empty((image_shape[0], image_shape[1], pano.shape[2]), dtype=pano.dtype)
    for i in range(pano.shape[2]):
        image[:, :, i] = ndimage.map_coordinates(pano[:, :, i], cp.stack([v, u]), order=1, mode='wrap')

    return image
python transformation perspectivecamera panoramas
1个回答
0
投票

我仍然不是 100% 确定原因,但我通过使用旋转矩阵的逆并翻转方向的 x 分量解决了我的问题。

我添加了

orientation[0] *= -1

并更换

R = calculate_R(orientation)

R = cp.linalg.inv(calculate_R(orientation))
© www.soinside.com 2019 - 2024. All rights reserved.