使用Scipy/Numpy仅获取浊点2D插值中的"有效"点

hel*_*ker 6 3d numpy scipy smoothing

我有一个从人的背部摄影测量得到的浊点.我正在尝试插入它来获得一个规则的网格,为此我scipy.interpolate到目前为止使用的效果很好.问题是:我正在使用的函数(scipy.interpolate.griddata)在平面x,y中使用云点的凸包,因此给出了原始表面中不存在的具有凹周长的一些值.

下图显示了左侧的原始cloudpoint(显示为水平线的内容实际上是一个密集的线形云点),结果griddata让我处于中间位置,我希望得到的结果在右边 - - x,y平面上的云点的"阴影"类型,其中原始表面中的不存在点将为零或Nans.

在此输入图像描述

我知道我可以删除cloudpoint上的Z坐标并检查每个网格位置是否接近,但这是如此暴力,我相信这应该是点云应用程序的常见问题.另一种可能是在点云上执行一些numpy操作,找到一个numpy掩码或布尔2D数组来"应用"结果griddata,但我没有找到任何(这些操作有点超出我的Numpy/Scipy知识).

有什么建议吗?

谢谢阅读!

pv.*_*pv. 5

使用可以快速构造合适的口罩KDTree。griddata使用的插值算法没有“有效”点的概念,因此您需要在插值之前或之后调整数据。

之前:

import numpy as np
from scipy.spatial import cKDTree as KDTree
from scipy.interpolate import griddata
import matplotlib.pyplot as plt

# Some input data
t = 1.2*np.pi*np.random.rand(3000)
r = 1 + np.random.rand(t.size)
x = r*np.cos(t)
y = r*np.sin(t)
z = x**2 - y**2

# -- Way 1: seed input with nan

def excluding_mesh(x, y, nx=30, ny=30):
    """
    Construct a grid of points, that are some distance away from points (x, 
    """

    dx = x.ptp() / nx
    dy = y.ptp() / ny

    xp, yp = np.mgrid[x.min()-2*dx:x.max()+2*dx:(nx+2)*1j,
                      y.min()-2*dy:y.max()+2*dy:(ny+2)*1j]
    xp = xp.ravel()
    yp = yp.ravel()

    # Use KDTree to answer the question: "which point of set (x,y) is the
    # nearest neighbors of those in (xp, yp)"
    tree = KDTree(np.c_[x, y])
    dist, j = tree.query(np.c_[xp, yp], k=1)

    # Select points sufficiently far away
    m = (dist > np.hypot(dx, dy))
    return xp[m], yp[m]

# Prepare fake data points
xp, yp = excluding_mesh(x, y, nx=35, ny=35)
zp = np.nan + np.zeros_like(xp)

# Grid the data plus fake data points
xi, yi = np.ogrid[-3:3:350j, -3:3:350j]
zi = griddata((np.r_[x,xp], np.r_[y,yp]), np.r_[z, zp], (xi, yi),
              method='linear')
plt.imshow(zi)
plt.show()
Run Code Online (Sandbox Code Playgroud)

想法是用包含nan值的伪数据点“播种”输入数据。使用线性插值时,这些将遮挡图像附近没有实际数据点的区域。

您还可以在插值后清除无效数据:

# -- Way 2: blot out afterward

xi, yi = np.mgrid[-3:3:350j, -3:3:350j]
zi = griddata((x, y), z, (xi, yi))

tree = KDTree(np.c_[x, y])
dist, _ = tree.query(np.c_[xi.ravel(), yi.ravel()], k=1)
dist = dist.reshape(xi.shape)
zi[dist > 0.1] = np.nan

plt.imshow(zi)
plt.show()
Run Code Online (Sandbox Code Playgroud)