网格和标记3D点

发布于 2025-02-05 08:25:18 字数 1393 浏览 1 评论 0原文

我的矩阵为3D点。我想将它们量化为空间网格,并以其网格编号表示该矩阵。 假设矩阵是 d

D = np.array([[-45.08341177,  34.40457052,   7.63253164],
       [-46.81391587,  34.35034554,   8.08080687],
       [-48.25988676,  34.29036266,   8.11271667],
       [-42.78217419,  24.51951629,   5.04130893],
       [-44.50295096,  25.34408096,   5.26748238],
       [-46.18559432,  25.60061165,   5.19218065]])

我将x,y和z放入数组中,

x = D[:,0]
y = D[:,1]
z = D[:,2]

现在我在上述代码上找到了空间网格的极限

r = np.zeros(x.shape)
n = 25
xE =  np.linspace(np.min(x), np.max(x), num = n+1 )
yE =  np.linspace(np.min(y), np.max(y), num = n+1 )
zE =  np.linspace(np.min(z), np.max(z), num = n+1 )

,n显示了网格大小。在这种情况下,它是nxnxn,因为空间为3D。

现在我想标记每个点。这是在此链接

如果任何专家可以帮助您,则只有下面给出的代码不会进入Python。

[MATLAB版本]

idx = 1;
for ii = 1:numel(xE)-1
    for jj = 1:numel(yE)-1
        for kk = 1:numel(zE)-1
            r(x>xE(ii) & x<=xE(ii+1)  & y>yE(jj) & y<=yE(jj+1) & z>zE(kk) & z<=zE(kk+1)) = idx;
            idx = idx + 1;
        end
    end
end

I have matrix of 3D points. I want to quantize them into spatial grid and late represent that matrix by their grid number.
Let say the matrix is D

D = np.array([[-45.08341177,  34.40457052,   7.63253164],
       [-46.81391587,  34.35034554,   8.08080687],
       [-48.25988676,  34.29036266,   8.11271667],
       [-42.78217419,  24.51951629,   5.04130893],
       [-44.50295096,  25.34408096,   5.26748238],
       [-46.18559432,  25.60061165,   5.19218065]])

I take x, y, and z into arrays

x = D[:,0]
y = D[:,1]
z = D[:,2]

Now I find the limit of spatial grid

r = np.zeros(x.shape)
n = 25
xE =  np.linspace(np.min(x), np.max(x), num = n+1 )
yE =  np.linspace(np.min(y), np.max(y), num = n+1 )
zE =  np.linspace(np.min(z), np.max(z), num = n+1 )

on above code, n shows the grid size. In this case it is nxnxn as space is 3D.

Now I want to label each point. This is done in Matlab on this link.

Only the code given below part is not getting into Python, if any expert may kindly help.

[Matlab version]

idx = 1;
for ii = 1:numel(xE)-1
    for jj = 1:numel(yE)-1
        for kk = 1:numel(zE)-1
            r(x>xE(ii) & x<=xE(ii+1)  & y>yE(jj) & y<=yE(jj+1) & z>zE(kk) & z<=zE(kk+1)) = idx;
            idx = idx + 1;
        end
    end
end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

顾铮苏瑾 2025-02-12 08:25:18

可能有更聪明的方法可以做到这一点,但这将完成工作。看来您想跨过3D垃圾箱,并使用垃圾箱“数字”作为位于该垃圾箱中的任何点的标签。

您可以使用np.histogramdd获取每个轴的边缘。然后迭代每对边缘以创建一个3D垃圾箱,然后检查哪个点位于该垃圾箱内。您可以使用itertools.product来浏览所有边的组合。

import numpy as np
from itertools import product

D = np.array([[-45.08341177,  34.40457052,   7.63253164],
       [-46.81391587,  34.35034554,   8.08080687],
       [-48.25988676,  34.29036266,   8.11271667],
       [-42.78217419,  24.51951629,   5.04130893],
       [-44.50295096,  25.34408096,   5.26748238],
       [-46.18559432,  25.60061165,   5.19218065]])

r = np.zeros(len(D), dtype=np.int64)
n = 25

_, (x_edges, y_edges, z_edges) = np.histogramdd(D, bins=(n, n, n))
# to account for the last edge being exactly at the max, we add a buffer
x_edges[-1] *= 1.00001
y_edges[-1] *= 1.00001
z_edges[-1] *= 1.00001

x_pairs = zip(x_edges, x_edges[1:])
y_pairs = zip(y_edges, y_edges[1:])
z_pairs = zip(z_edges, z_edges[1:])
bin_edge_iter = product(x_pairs, y_pairs, z_pairs)

for label, ((x0, x1), (y0, y1), (z0, z1)) in enumerate(bin_edge_iter):
    ix = (
        (x0 <= D[:,0]) & (D[:,0] < x1) 
        & (y0 <= D[:,1]) & (D[:,1] < y1) 
        & (z0 <= D[:2]) & (D[:2] < z1)
    )
    r[ix] = label

您要求将其作为函数,但是在这种情况下,对象更合适。我们需要存储有关垃圾箱边缘的信息。

class BinLabeller3D:
    """Fits bins to data and assigns new data points a label."""
    def __init__(self, num_bins: int) -> None:
        self.num_bins = num_bins
        self.x_edges = None
        self.y_edges = None
        self.z_edges = None
        self._fit = False

    def __repr__(self) -> str:
        n = self.__class__.__name__
        return f'<{n} num_bins={self.num_bins} at 0x{id(self):x}>'

    def __call__(self, data) -> np.array:
        return self.predict(data)

    def fit(self, data: np.array):
        """Fits the (num_bins x num_bins x num_bins) bin edges to the data.
        
        args:
            data: (array-like) an N x 3 sized array
        """
        _, (x_edges, y_edges, z_edges) = np.histogramdd(
            data,
            bins=(self.num_bins, self.num_bins, self.num_bins)
        )

        # to account for the last edge being exactly at the max, we add a buffer
        self.x_edges = x_edges
        self.y_edges = y_edges
        self.z_edges = z_edges
        self.x_edges[-1] *= 1.00001
        self.y_edges[-1] *= 1.00001
        self.z_edges[-1] *= 1.00001
        self._fit = True
        return self

    def predict(self, data: np.array) -> np.array:
        """Predicts the label for a new data point.
        
        args:
            data: (array-like) and N x 3 sized array.
        returns:
            labels: (np.array) a 1D array of bin labels.  Points outside of
                the bin range are labelled as -1.
        """
        if not self._fit:
            raise ValueError('Model must be fit before making a prediction')
        data = np.array(data)

        # if a single point is passed, convert it to a 2D array.
        if data.ndim == 1:
            data = data.reshape(-1, len(data))
        
        # check the shape
        if data.shape[-1] != 3:
            raise ValueError('The dimension of `data` must be (..., 3), '
                f'got {data.shape}')

        x_pairs = zip(self.x_edges, self.x_edges[1:])
        y_pairs = zip(self.y_edges, self.y_edges[1:])
        z_pairs = zip(self.z_edges, self.z_edges[1:])
        bin_edge_iter = product(x_pairs, y_pairs, z_pairs)

        # set all labels to -1, which indicates and out-of-range bin
        labels = np.zeros(len(data), dtype=np.int64) - 1

        for label, ((x0, x1), (y0, y1), (z0, z1)) in enumerate(bin_edge_iter):
            ix = (
                (x0 <= D[:,0]) & (D[:,0] < x1) 
                & (y0 <= D[:,1]) & (D[:,1] < y1) 
                & (z0 <= D[:2]) & (D[:2] < z1)
            )
            labels[ix] = label
        return labels

您会这​​样使用它:

bin_labeller = BinLabeller3D(25)
bin_labeller.fit(D)

new_points = np.array([
       [-47.26760012,  26.26654462,   8.84124020],
       [-43.21719762,  23.46974622,   7.16000541],
       [-44.10245666,  29.44169842,   6.18476654]
])

new_labels = bin_labeller(new_points)

There is probably more clever way to do this, but this will get the job done. It looks like you want to step through a 3D grid of bins and use the bin "number" as a label for any points that reside in that bin.

You can use np.histogramdd to get the edges for each axis. Then iterate through each pair of edges to create a 3D bin, and check which points fall within that bin. You can use itertools.product to walk through all combinations of edges.

import numpy as np
from itertools import product

D = np.array([[-45.08341177,  34.40457052,   7.63253164],
       [-46.81391587,  34.35034554,   8.08080687],
       [-48.25988676,  34.29036266,   8.11271667],
       [-42.78217419,  24.51951629,   5.04130893],
       [-44.50295096,  25.34408096,   5.26748238],
       [-46.18559432,  25.60061165,   5.19218065]])

r = np.zeros(len(D), dtype=np.int64)
n = 25

_, (x_edges, y_edges, z_edges) = np.histogramdd(D, bins=(n, n, n))
# to account for the last edge being exactly at the max, we add a buffer
x_edges[-1] *= 1.00001
y_edges[-1] *= 1.00001
z_edges[-1] *= 1.00001

x_pairs = zip(x_edges, x_edges[1:])
y_pairs = zip(y_edges, y_edges[1:])
z_pairs = zip(z_edges, z_edges[1:])
bin_edge_iter = product(x_pairs, y_pairs, z_pairs)

for label, ((x0, x1), (y0, y1), (z0, z1)) in enumerate(bin_edge_iter):
    ix = (
        (x0 <= D[:,0]) & (D[:,0] < x1) 
        & (y0 <= D[:,1]) & (D[:,1] < y1) 
        & (z0 <= D[:2]) & (D[:2] < z1)
    )
    r[ix] = label

You requested this as a function, but an object is more appropriate in this case. We need to store the information about the bin edges.

class BinLabeller3D:
    """Fits bins to data and assigns new data points a label."""
    def __init__(self, num_bins: int) -> None:
        self.num_bins = num_bins
        self.x_edges = None
        self.y_edges = None
        self.z_edges = None
        self._fit = False

    def __repr__(self) -> str:
        n = self.__class__.__name__
        return f'<{n} num_bins={self.num_bins} at 0x{id(self):x}>'

    def __call__(self, data) -> np.array:
        return self.predict(data)

    def fit(self, data: np.array):
        """Fits the (num_bins x num_bins x num_bins) bin edges to the data.
        
        args:
            data: (array-like) an N x 3 sized array
        """
        _, (x_edges, y_edges, z_edges) = np.histogramdd(
            data,
            bins=(self.num_bins, self.num_bins, self.num_bins)
        )

        # to account for the last edge being exactly at the max, we add a buffer
        self.x_edges = x_edges
        self.y_edges = y_edges
        self.z_edges = z_edges
        self.x_edges[-1] *= 1.00001
        self.y_edges[-1] *= 1.00001
        self.z_edges[-1] *= 1.00001
        self._fit = True
        return self

    def predict(self, data: np.array) -> np.array:
        """Predicts the label for a new data point.
        
        args:
            data: (array-like) and N x 3 sized array.
        returns:
            labels: (np.array) a 1D array of bin labels.  Points outside of
                the bin range are labelled as -1.
        """
        if not self._fit:
            raise ValueError('Model must be fit before making a prediction')
        data = np.array(data)

        # if a single point is passed, convert it to a 2D array.
        if data.ndim == 1:
            data = data.reshape(-1, len(data))
        
        # check the shape
        if data.shape[-1] != 3:
            raise ValueError('The dimension of `data` must be (..., 3), '
                f'got {data.shape}')

        x_pairs = zip(self.x_edges, self.x_edges[1:])
        y_pairs = zip(self.y_edges, self.y_edges[1:])
        z_pairs = zip(self.z_edges, self.z_edges[1:])
        bin_edge_iter = product(x_pairs, y_pairs, z_pairs)

        # set all labels to -1, which indicates and out-of-range bin
        labels = np.zeros(len(data), dtype=np.int64) - 1

        for label, ((x0, x1), (y0, y1), (z0, z1)) in enumerate(bin_edge_iter):
            ix = (
                (x0 <= D[:,0]) & (D[:,0] < x1) 
                & (y0 <= D[:,1]) & (D[:,1] < y1) 
                & (z0 <= D[:2]) & (D[:2] < z1)
            )
            labels[ix] = label
        return labels

You would use it like this:

bin_labeller = BinLabeller3D(25)
bin_labeller.fit(D)

new_points = np.array([
       [-47.26760012,  26.26654462,   8.84124020],
       [-43.21719762,  23.46974622,   7.16000541],
       [-44.10245666,  29.44169842,   6.18476654]
])

new_labels = bin_labeller(new_points)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文