繁体   English   中英

通过引用组合NumPy阵列

[英]Combine NumPy Arrays by Reference

我想在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级的正确数据。 这没关系。

您可以创建自己的类来管理引用过程,如下例所示。 你应该进一步研究这个问题,包括使用__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和像这样的表面(在每一行中注意“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。

如上所述,我不确定你的最后任务是什么,但这就是我如何做到的。
例如,使用openCV lib加载图像并将其转换为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)

但可能是你想做别的事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM