根据距最近像素的距离,将连续值的贡献放入离散的 2D 网格中

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

我有一个包含点坐标的 numpy 数组(在 3D 中,但我首先尝试 1D 和 2D 中的方法),我想将其放入离散网格中。但是,我不想只是将点移动到它们最接近的网格像素,而是在每个像素上放置一个加权值,该值取决于该点实际距该像素的距离。例如,如果在 1D 中我有一个点 x = 15.4,在我的离散空间中,该点将为像素 15 贡献 60%,为像素 16 贡献 40%。我已经设法在 1D 中做到这一点,代码如下:

# Make test data

N = 1000

data = np.random.normal(
    loc = 10,
    scale = 2,
    size = N
)

# set data range, binsize, and coordinates
xmin = 0
xmax = 20
xbinsize = 0.5

# define the bin centres
xbincenters = np.arange(
    xmin+xbinsize*0.5,
    xmax,
    xbinsize
)

# transform data and floor it to get the closest pixel in the discrete grid
data_t = data/xbinsize - 0.5
bin_indices = np.floor(data_t).astype(int)
# calculate the difference between continuous coordinate and closest pixel
dx = data_t - bin_indices

# get data range in bin indices

index_min = np.ceil(xmin/xbinsize - 0.5).astype(int)
index_max = np.ceil(xmax/xbinsize - 0.5).astype(int)

# do the interpolation

minlength = index_max - index_min

output_array = np.bincount(
    bin_indices,
    weights = (1-dx),
    minlength = minlength
) +\
np.bincount(
    bin_indices+1,
    weights = dx,
    minlength = minlength
)

# finally plot a histogram of the continuous values against output_array
fig,ax = plt.subplots()
ax.hist(data, bins=np.arange(0,20,0.5))
ax.plot(
    xbincenters,
    output_array,
    color = 'r'
)
plt.show()

comparison plot

我一直试图将其推广到 2D 但无济于事,因为

np.bincount()
只适用于 1D 数组。

在尝试找到最近的像素之前,我觉得代码应该类似,因为上面的所有操作都可以广播到二维数组。在这种情况下,我们需要将任何坐标分配到最近的 4 个像素,具体取决于差异

dx
和现在的另一个差异
dy
(如果您将上面的代码用于形状为
(1000, 2)
的数组,则将是分别是数组的第一列和第二列
dx
)。我尝试解开我的
bin_indices
dx
数组以在它们上使用
np.bincount()
,但此时我不确定这是否正确或对解开的数组执行哪些操作。在 2D(以及后来的 3D)中推广这个问题是否需要一种不同的方法?任何帮助将不胜感激,提前谢谢您!

python numpy interpolation data-analysis bilinear-interpolation
1个回答
0
投票

所以,如果我理解正确,那么您“手动”完成了所有插值工作(可能有一些代码可以在某处执行此操作,但现在想不出任何代码),并使用

bincount
只是为了增加输出数组(因为如果索引包含重复,
output_array[indices] += weight
确实不起作用)

然后,您只需修改索引即可将自己定位为二维数组。使用宽度和高度,并使用

indicesy*width+indicesx
作为索引。然后完成后“解开”数组。

像这样

import numpy as np
import matplotlib.pyplot as plt

N = 1000

# Big array for performance test
datax = np.random.normal(
    loc = 10,
    scale = 2,
    size = N
)
datay = np.random.normal(
    loc = 10,
    scale = 2,
    size = N
)

# Or small one for result test (comment if not wanted)
datax = np.array([15.2, 1.5, 15.3])
datay = np.array([5.1, 10.5, 15.9])


# set data range, binsize, and coordinates
xmin = 0
xmax = 20
xbinsize = 0.5
ymin = 0
ymax = 20
ybinsize = 0.5

# define the bin centres
xbincenters = np.arange(
    xmin+xbinsize*0.5,
    xmax,
    xbinsize
)
ybincenters = np.arange(
    ymin+ybinsize*0.5,
    ymax,
    ybinsize
)

# transform data and floor it to get the closest pixel in the discrete grid
datax_t = datax/xbinsize - 0.5
datay_t = datay/ybinsize - 0.5
bin_indicesx = np.floor(datax_t).astype(int)
bin_indicesy = np.floor(datay_t).astype(int)
# calculate the difference between continuous coordinate and closest pixel
dx = datax_t - bin_indicesx
dy = datay_t - bin_indicesy

# get data range in bin indices

index_minx = np.ceil(xmin/xbinsize - 0.5).astype(int)
index_miny = np.ceil(ymin/ybinsize - 0.5).astype(int)
index_maxx = np.ceil(xmax/xbinsize - 0.5).astype(int)
index_maxy = np.ceil(ymax/ybinsize - 0.5).astype(int)

# do the interpolation

minlengthx = index_maxx - index_minx
minlengthy = index_maxy - index_miny
minlength=minlengthx*minlengthy

flat_output_array = np.bincount(
    bin_indicesy*minlengthx+bin_indicesx,
    weights = (1-dx)*(1-dy),
    minlength = minlength
) +\
np.bincount(
    bin_indicesy*minlengthx+bin_indicesx+1,
    weights = dx*(1-dy),
    minlength = minlength
) +\
np.bincount(
    (bin_indicesy+1)*minlengthx+bin_indicesx,
    weights = (1-dx)*dy,
    minlength = minlength
) +\
np.bincount(
    (bin_indicesy+1)*minlengthx+bin_indicesx+1,
    weights = dx*dy,
    minlength = minlength
) 

output_array=flat_output_array.reshape(-1, minlengthx)

# finally plot a histogram of the continuous values against output_array
plt.imshow(output_array)

plt.show()

© www.soinside.com 2019 - 2024. All rights reserved.