代码之家  ›  专栏  ›  技术社区  ›  Jacques

将平面拟合到二维阵列

  •  5
  • Jacques  · 技术社区  · 9 年前

    我有一个拓扑图像,我正试图使用Python执行平面减法。该图像是一个256x256二维数组,包含0到1之间的float32值。

    我想做的是使用线性回归来拟合一个平面,然后从原始值中减去这个平面。

    我不确定如何实现这一目标。

    我是Python语言的新手,感谢任何帮助。

    1 回复  |  直到 9 年前
        1
  •  8
  •   Anton    9 年前

    首先,您需要以正确的方式表示数据。

    你有两个论点 X1 X2 ,定义拓扑图像的坐标,以及一个目标值 Y ,定义每个点的高度。对于回归分析,您需要通过添加 X0 ,始终等于1。

    然后需要将参数和目标展开为矩阵 [m*m x 3] [m*m x 1] 分别地你想找到向量 theta ,其将描述期望的平面。为此,您可以使用 法线方程 :

    enter image description here

    为了演示该方法,我生成了一些拓扑曲面。您可以在图片上看到曲面、带有拟合平面的曲面以及相减后的曲面:

    regression plane

    下面是代码:

    from mpl_toolkits.mplot3d import Axes3D
    import matplotlib.pyplot as plt
    import numpy as np
    
    m = 256 #size of the matrix
    
    X1, X2 = np.mgrid[:m, :m]
    
    fig = plt.figure()
    ax = fig.add_subplot(3,1,1, projection='3d')
    jet = plt.get_cmap('jet')
    
    #generation of the surface
    F = 3        
    i = np.minimum(X1, m-X1-1)
    j = np.minimum(X2, m-X2-1)
    H = np.exp(-.5*(np.power(i, 2)  +  np.power(j, 2)   )/(F*F))
    Y = np.real(  np.fft.ifft2   (H  *  np.fft.fft2(  np.random.randn(m, m))))
    a = 0.0005; b = 0.0002; #parameters of the tilted plane
    Y = Y + (a*X1 + b*X2); #adding the plane
    Y = (Y - np.min(Y)) / (np.max(Y) - np.min(Y)) #data scaling
    
    #plot the initial topological surface
    ax.plot_surface(X1,X2,Y, rstride = 1, cstride = 1, cmap = jet, linewidth = 0)
    
    
    #Regression
    X = np.hstack(   ( np.reshape(X1, (m*m, 1)) , np.reshape(X2, (m*m, 1)) ) )
    X = np.hstack(   ( np.ones((m*m, 1)) , X ))
    YY = np.reshape(Y, (m*m, 1))
    
    theta = np.dot(np.dot( np.linalg.pinv(np.dot(X.transpose(), X)), X.transpose()), YY)
    
    plane = np.reshape(np.dot(X, theta), (m, m));
    
    ax = fig.add_subplot(3,1,2, projection='3d')
    ax.plot_surface(X1,X2,plane)
    ax.plot_surface(X1,X2,Y, rstride = 1, cstride = 1, cmap = jet, linewidth = 0)
    
    
    #Subtraction
    Y_sub = Y - plane
    ax = fig.add_subplot(3,1,3, projection='3d')
    ax.plot_surface(X1,X2,Y_sub, rstride = 1, cstride = 1, cmap = jet, linewidth = 0)
    
    plt.show()