交换numpy数组的子数组

3

首先给出一些背景信息。

我正在尝试使用Cairo(实际上是pycairo)将内容绘制到Gdk(实际上是pygtk)pixbuf中。我的原始代码如下:

import cairo as C
import gtk.gdk as GG

FMT = C.FORMAT_ARGB32
CSP = GG.COLORSPACE_RGB

st = C.ImageSurface.format_stride_for_width(FMT, zw)
surf = C.ImageSurface(FMT, zw, zh)
c = C.Context(surf)

# draw into c here ...

pixels = surf.get_data()
return GG.pixbuf_new_from_data(pixels, CSP, True, 8, zw, zh, st)

有一段时间,这似乎只是有效的,直到我尝试绘制颜色而不仅仅是黑色文本。事实证明,这两个库在字节顺序上存在分歧,如下:

# !!! FIXME !!! cairo ARGB surfaces and gdk pixbufs disagree on bytesex:
# cairo: LSB --> B G R A <-- MSB
# gdk:   LSB --> R G B A <-- MSB
# !!! WTF !!!

在将像素缓冲区从缓冲区传输到屏幕后,结果是图像的红色和蓝色通道被交换了。

因此,如果我要继续使用像素缓冲区(就像我想要的那样),我需要对数据进行后处理,交换每个第1个字节和每个第3个字节。 我可以在纯Python中完成这个操作:

def changesex(data):
    i0 = 0
    i2 = 2
    l = len(data)
    while i2 < l:
        temp = data[i0]
        data[i0] = data[i2]
        data[i2] = temp
        i0 += 4
        i2 += 4

但我认为如果有一个用C语言编写的内置操作符,使用numpy可能会更快。类似于这样:

a = np.frombuffer(data, dtype=np.uint8)
a.shape = (len(data) / 4, 4)
temp = a[:,0]
a[:,0] = a[:,2]
a[:,2] = temp

我只是在做梦吗?

1个回答

6

考虑到你最初给出的(N,4)数组是B,G,R,A,你可以使用一些高级索引非常简单地将其表示为(N,4)格式的R,G,B,A

a = np.frombuffer(data, dtype=np.uint8)
a.shape = (-1, 4)
rearranged = a[:,[2,1,0,3]]

是的,我通过试错和查看类似问题的解决方案自己找到了答案。不过还是谢谢你! - BehemothTheCat
对我来说,使用a[:,:,[2,1,0,3]]就可以重新排列,不需要额外的shape命令。 - Oliver Zendel
此外,rearranged = a[...,[2,1,0,3]] 可以适用于任意数量的轴(例如,批量学习或其他类似的应用)。 - Poik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接