4

我想在 O(1) 中将两个数组组合成一个新数组。然后,我想更改这个新数组中的值以更改旧数组中的值。

这是在 PyGame 的 surfarray 模块的上下文中,它没有返回 RGBA (n*m*4) 数组的函数 - 仅分别返回 RGB (n*m*3) 和 A (n*m) 数组。理想情况下,我会在 O(1) 中创建一个新数组“RGBA”,它引用“RGB”和“A”数组。改变“RGBA”会改变“RGB”和“A”,从而改变表面。

我不知道这是否可能,因为我想不出用 C 做的方法。但是,我可以想到一些想法。例如,也许有一个 numpy 数组类型,它封装了一些子数组,并在内部将索引重定向到 C 级别的正确索引。这样就好了。

4

2 回答 2

1

您可以创建自己的类来管理引用过程,如下例所示。__getslice__您应该在这方面进一步工作,以包括使用、__add__、等的切片功能__mul__

import numpy as np
a1 = np.arange(1,11)
a2 = np.arange(101,111)
class Combiner():
    def __init__(self, *args):
        self.arrays = [arg for arg in args]
        self.lens = [len(arg) for arg in args]
    def __getitem__(self,i):
        if i >=0:
            shift = 0
            acc = 0
            for j,l in enumerate(self.lens):
                acc += l
                if i<acc:
                    return self.arrays[j][i-shift]
                shift += l
        if i<0:
            shift = 0
            acc = 0
            for j in xrange(len(self.lens)-1,-1,-1):
                l = self.lens[j]
                acc -= l
                if i>=acc:
                    return self.arrays[j][i+shift]
                shift += l

    def __setitem__(self,i,v):
        if i >=0:
            shift = 0
            acc = 0.
            for j,l in enumerate(self.lens):
                acc += l
                if i<acc:
                    self.arrays[j][i-shift] = v
                    return
                shift += l
        if i<0:
            shift = 0
            acc = 0
            for j in xrange(len(self.lens)-1,-1,-1):
                l = self.lens[j]
                acc -= l
                if i>=acc:
                    self.arrays[j][i+shift] = v
                    return
                shift += l

a3 = Combiner(a1,a2)
print a3[-10]
# 101
a3[-2] = 22222
a3[ 4] = 11111
print a1
#[    1     2     3     4 11111     6     7     8     9    10]
print a2
#[  101   102   103   104   105   106   107   108 22222   110]
于 2013-05-09T15:22:41.840 回答
0

我不确定我是否完全理解了这个问题。据我所知,如果你初始化 pygame 和像这样的表面(注意每行中的“32”),pygame 表面是 RGBA(准确地说,BGRA)连续数组:

# display surface
DISP = pygame.display.set_mode((window_w, window_h), 0, 32)
# some surface
window = pygame.Surface((w, h), 0, 32) 

此外,我建议尽可能使用 32 位,而不是 24 位,因为 24 位表面很难与数组互操作(我numpy用于存储和操作图像数据)。
例如,如果我没记错的话,一个 24 位表面必须具有可被 4 整除的像素数量。

如前所述,我不确定您的最终任务是什么,但这就是我的做法。
例如,使用 lib 加载图像openCV并将其转换为 BGRA 数组:

# BGR 3d numpy array array (shape = h, w, 3) with image data
img = cv2.imread(filename)
# BGRA 3d numpy array (shape = h, w, 4) 
img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)

然后这个函数将整个数组数据复制到一个表面中,只需要确保它们具有相同的像素大小:

# copy array data into a pygame surface
def copy_arr(surface, myarray):
    bv = surface.get_buffer()
    bv.write(myarray.tostring(), 0)

但也可能是你想做其他事情。

于 2016-04-10T21:42:05.027 回答