Python:以分数形式缩小/扩展二维数组

发布于 2024-12-28 20:35:48 字数 1829 浏览 3 评论 0原文

存在 2D 数字数组,作为某些数值过程的输出,其形状为 1x1、3x3、5x5、... 形状,对应于不同的分辨率。

在一个阶段中,需要生成形状为 nxn 的平均值,即二维数组值。 如果输出的形状一致,即全部为 11x11,则解决方案是显而易见的,因此:

element_wise_mean_of_all_arrays

然而,对于这篇文章的问题,数组的形状不同,所以明显的方法不起作用!

我认为使用 kron 可能会有所帮助 函数 但它没有。例如,如果数组的形状为 17x17,如何将其变为 21x21。因此,对于 1x13x3 等所有其他数组,要构建一个常量形状的数组,例如 21x21。 与目标形状相比,阵列的形状也可能更小或更大。这是一个要压缩为 21x2131x31 数组。

您可以将这个问题想象为图像缩小或扩展的一个非常常见的任务。

在 Python 中,使用 numpy、scipy 等在 2D 数组上执行相同工作的有效方法是什么?

更新: 以下是已接受答案的稍微优化版本:


def resize(X,shape=None):
    if shape==None:
        return X
    m,n = shape
    Y = np.zeros((m,n),dtype=type(X[0,0]))
    k = len(X)
    p,q = k/m,k/n
    for i in xrange(m):
        Y[i,:] = X[i*p,np.int_(np.arange(n)*q)]
    return Y

它工作得很好,但是你们都同意就效率而言它是最佳选择吗?如果没有改善的话?


# Expanding ---------------------------------

>>> X = np.array([[1,2,3],[4,5,6],[7,8,9]])
[[1 2 3]
 [4 5 6]
 [7 8 9]]

>>> resize(X,[7,11])
[[1 1 1 1 2 2 2 2 3 3 3]
 [1 1 1 1 2 2 2 2 3 3 3]
 [1 1 1 1 2 2 2 2 3 3 3]
 [4 4 4 4 5 5 5 5 6 6 6]
 [4 4 4 4 5 5 5 5 6 6 6]
 [7 7 7 7 8 8 8 8 9 9 9]
 [7 7 7 7 8 8 8 8 9 9 9]]

# Shrinking ---------------------------------

>>> X = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]
 [13 14 15 16]]

>>> resize(X,(2,2))
[[ 1  3]
 [ 9 11]]

最后一点:上面的代码可以很容易地转换为 Fortran 以获得尽可能最高的性能。

There are 2D arrays of numbers as outputs of some numerical processes in the form of 1x1, 3x3, 5x5, ... shaped, that correspond to different resolutions.

In a stage an average i.e., 2D array value in the shape nxn needs to be produced.
If the outputs were in consistency of shape i.e., say all in 11x11 the solution was obvious, so:

element_wise_mean_of_all_arrays.

For the problem of this post however the arrays are in different shapes so the obvious way does not work!

I thought it might be some help by using kron function however it didn't. For example, if array is in shape of 17x17 how to make it 21x21. So for all others from 1x1,3x3,..., to build a constant-shaped array, say 21x21.
Also it can be the case that the arrays are smaller and bigger in shape compared to the target shape. That is an array of 31x31 to be shruk into 21x21.

You could imagine the problem as a very common task for images, being shrunk or extended.

What are possible efficient approaches to do the same jobs on 2D arrays, in Python, using numpy, scipy, etc?

Updates:
Here is a bit optimized version of the accepted answer bellow:


def resize(X,shape=None):
    if shape==None:
        return X
    m,n = shape
    Y = np.zeros((m,n),dtype=type(X[0,0]))
    k = len(X)
    p,q = k/m,k/n
    for i in xrange(m):
        Y[i,:] = X[i*p,np.int_(np.arange(n)*q)]
    return Y

It works perfectly, however do you all agree it is the best choice in terms of the efficiency? If not any improvement?


# Expanding ---------------------------------

>>> X = np.array([[1,2,3],[4,5,6],[7,8,9]])
[[1 2 3]
 [4 5 6]
 [7 8 9]]

>>> resize(X,[7,11])
[[1 1 1 1 2 2 2 2 3 3 3]
 [1 1 1 1 2 2 2 2 3 3 3]
 [1 1 1 1 2 2 2 2 3 3 3]
 [4 4 4 4 5 5 5 5 6 6 6]
 [4 4 4 4 5 5 5 5 6 6 6]
 [7 7 7 7 8 8 8 8 9 9 9]
 [7 7 7 7 8 8 8 8 9 9 9]]

# Shrinking ---------------------------------

>>> X = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]
 [13 14 15 16]]

>>> resize(X,(2,2))
[[ 1  3]
 [ 9 11]]

Final note: that the code above easily could be translated to Fortran for the highest performance possible.

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

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

发布评论

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

评论(1

狂之美人 2025-01-04 20:35:48

我不确定我到底理解你正在尝试什么,但如果我认为最简单的方法是:

wanted_size = 21
a = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
b = numpy.zeros((wanted_size, wanted_size))

for i in range(wanted_size):
    for j in range(wanted_size):
        idx1 = i * len(a) / wanted_size
        idx2 = j * len(a) / wanted_size
        b[i][j] = a[idx1][idx2]

你可以用一些自定义函数(例如平均值)替换 b[i][j] = a[idx1][idx2]以 [idx1][idx2] 或某个插值函数为中心的 3x3 矩阵。

I'm not sure I understand exactly what you are trying but if what I think the simplest way would be:

wanted_size = 21
a = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
b = numpy.zeros((wanted_size, wanted_size))

for i in range(wanted_size):
    for j in range(wanted_size):
        idx1 = i * len(a) / wanted_size
        idx2 = j * len(a) / wanted_size
        b[i][j] = a[idx1][idx2]

You could maybe replace the b[i][j] = a[idx1][idx2] with some custom function like the average of a 3x3 matrix centered in a[idx1][idx2] or some interpolation function.

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