按引用组合NumPy数组



我想把两个数组组合成一个0(1)的新数组。然后,我想改变这个新数组中的值来改变旧数组中的值。

这是在PyGame的surfarray模块的上下文中,该模块没有返回RGBA (n*m*4)数组的函数——只有RGB (n*m*3)和a (n*m)数组。理想情况下,我会在0(1)中创建一个引用"RGB"one_answers"a"数组的新数组"RGBA"。改变"RGBA"会同时改变"RGB"one_answers"A",从而改变表面。

我不知道这是否可能,因为我想不出用c来做这件事的方法。然而,我可以想到一些主意。例如,可能存在一个numpy数组类型,它封装了一些子数组,并在内部将索引重定向到C级别的正确索引。

您可以创建自己的类来管理引用过程,如下面的示例所示。您应该进一步研究这一点,以包括__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]

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

# 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整除的像素量,如果我没有弄错的话。

如前所述,我不确定你的最终任务是什么,但我是这样做的。
例如,用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)

但也可以是你想做别的事情

最新更新