三维矩阵透视变换

时间:2014-03-04 14:58:23

标签: python opencv numpy matrix scipy

我正在使用阴影中的形状来生成使用安装在移动平台上的相机拍摄的图像的数字地形模型(DTM)。用Python编写的算法似乎工作得相当好,但输出是倾斜的,有点球形,所以我怀疑我需要从DTM中删除透视失真和破坏。以下DTM的视觉效果:

DTM of SfS result 数据可用here,以防任何人有兴趣参加此活动。

相机以41度倾斜安装,并具有以下相机和失真矩阵:

    cam_matrix = numpy.matrix([[246.00559,0.00000,169.87374],[0.00000,247.37317,132.21396],[0.00000,0.00000,1.00000]])
    distortion_matrix = numpy.matrix([0.04674, -0.11775, -0.00464, -0.00346, 0.00000])

如何应用透视变换并从此矩阵中移除滚动失真以获得展平的DTM?

我尝试使用OpenCV,但它不起作用,因为OpenCv期待一个图像,变换只是移动像素而不是操纵它们的值。我也研究了Numpy和Scipy但尚未得出结论或解决方案。我对这些变换背后的理论有些熟悉,但主要是在2D版本上工作。

有什么想法吗?

感谢。

2 个答案:

答案 0 :(得分:2)

您可以使用4 x 4变换矩阵,该矩阵是可逆的,允许在您想要的两个坐标系之间进行双向变换。

如果您分别知道三个轮换abg,关于xyz,请使用右侧 - 手规则。 x0y0z0是两个坐标系原点之间的转换。

转换矩阵定义为:

T = np.array([[ cos(b)*cos(g), (sin(a)*sin(b)*cos(g) + cos(a)*sin(g)), (sin(a)*sin(g) - cos(a)*sin(b)*cos(g)), x0],
              [-cos(b)*sin(g), (cos(a)*cos(g) - sin(a)*sin(b)*sin(g)), (sin(a)*cos(g) + cos(a)*sin(b)*sin(g)), y0],
              [        sin(b), -sin(a)*cos(b), cos(a)*cos(b), z0]
              [ 0, 0, 0, 1])

要有效地使用它,你应该把你的点放在二维数组中,如:

orig = np.array([[x0, x1, ..., xn],
                 [y0, y1, ..., yn],
                 [z0, z1, ..., zn],
                 [ 1,  1, ...,  1]])

然后:

new = T.dot(orig)

将为您提供转换后的点数。

答案 1 :(得分:0)

Saullo G. P. Castro 有一个很好的解释。这是我在Python 3.8中使用的代码。如果您使用T = make_matrix(90,0,0,1,0,0)行,您会看到orig矩阵中XYZ位置的变化。

#!/usr/bin/env python3
import numpy as np
import math
'''If you know the three rotations a, b and g, about x, y, z respectively, using the 
right-hand rule.
The x0, y0, z0 are the translations between the origins of the two coordinate 
systems.'''
#https://stackoverflow.com/questions/22175385/3d-matrix-perspective-transform/22311973#22311973

def make_matrix(roll,pitch,heading,x0,y0,z0):
    a = math.radians(roll)
    b = math.radians(pitch)
    g = math.radians(heading)

    T = np.array([[ math.cos(b)*math.cos(g), (math.sin(a)*math.sin(b)*math.cos(g) + 
    math.cos(a)*math.sin(g)), (math.sin(a)*math.sin(g) - 
    math.cos(a)*math.sin(b)*math.cos(g)), x0],
    [-math.cos(b)*math.sin(g), (math.cos(a)*math.cos(g) - 
    math.sin(a)*math.sin(b)*math.sin(g)), (math.sin(a)*math.cos(g) + 
    math.cos(a)*math.sin(b)*math.sin(g)), y0],
    [        math.sin(b), -math.sin(a)*math.cos(b), math.cos(a)*math.cos(b), z0],
    [ 0, 0, 0, 1]])
    return T

def load_orig():
    orig = np.array([[0, 1, 0],
                [0, 0, 1],
                [1, 0, 0],
                [ 1,  1, 1]])
    return orig

if __name__ == '__main__':
    T = make_matrix(90,0,0,1,0,0)
    orig = load_orig()
    new = T.dot(orig)
    print(new)