如何将 numpy 数组呈现到 pygame 表面?

How to present numpy array into pygame surface?

我正在编写一段代码,其中一部分是读取图像源并将其显示在屏幕上供用户交互。我还需要锐化的图像数据。我使用以下读取数据并将其显示在 pyGame

def image_and_sharpen_array(file_name):
    #read the image data and return it, with the sharpened image
    image = misc.imread(file_name)

    blurred = ndimage.gaussian_filter(image,3)
    edge = ndimage.gaussian_filter(blurred,1)
    alpha = 20
    out = blurred + alpha*(blurred - edge)
    return image,out

#get image data
scan,sharpen = image_and_sharpen_array('foo.jpg')
w,h,c = scan.shape


#setting up pygame
pygame.init()
screen = pygame.display.set_mode((w,h))

pygame.surfarray.blit_array(screen,scan)
pygame.display.update()

并且图像显示在屏幕上只是旋转和反转。这是因为 misc.imreadpyGame 之间的差异吗?或者这是由于我的代码有问题吗?

还有其他方法吗?我阅读的大多数解决方案都涉及保存图形,然后使用“pyGame”读取它。

我的建议是使用pygame.transform模块。有 fliprotate 方法,您可以使用它们来进行转换。查阅相关文档。

我的建议是将输出图像保存到一个新的 Surface,然后应用转换,然后 blit 显示。

temp_surf = pygame.Surface((w,h))
pygame.surfarray.blit(temp_surf, scan)

'''transform temp_surf'''

screen.blit(temp_surf, (0,0))

我不知道这是为什么。这可能与轴从二维数组传输到 pygame Surface.

的顺序有关

每个库都有自己的解释图像数组的方式。 'rotated' 我想你的意思是转置。这就是 PyGame 显示 numpy 数组的方式。有很多方法可以让它看起来 'correct'。实际上有很多方法甚至可以显示数组,这使您可以完全控制通道表示等。在 pygame 版本 1.9.2 中,这是我能实现的最快的数组渲染。 (请注意,对于早期版本,这将不起作用!)。 此函数将用数组填充表面:

def put_array(surface, myarr):          # put array into surface
    bv = surface.get_view("0")
    bv.write(myarr.tostring())

如果这不起作用,请使用它,应该在任何地方都有效:

# put array data into a pygame surface
def put_arr(surface, myarr):
    bv = surface.get_buffer()
    bv.write(myarr.tostring(), 0)

你可能还是得不到你想要的,所以它被转置或交换了颜色通道。这个想法是,以适合此表面缓冲区的形式管理您的阵列。要找出正确的通道顺序和轴顺序,请使用 openCV 库(cv2.imread(文件名))。使用 openCV,您可以按照标准 BGR 顺序打开图像,并且它具有很多转换功能。如果我没记错的话,当直接写入表面缓冲区时,BGR 是 24 位的正确顺序,BGRA 是 32 位表面的正确顺序。所以你可以尝试把你用这个函数从文件中取出的图像数组blit到屏幕上。

还有其他绘制数组的方法,例如这是整套辅助函数 http://www.pygame.org/docs/ref/surfarray.html
但我不建议使用它,因为表面不能直接操作像素,你可能会迷失在参考中。 小提示:做'signalling test'用图片,像这样。所以你会立即看到是否有问题,只需加载为数组并尝试渲染。

我经常使用numpy swapaxes()方法: 在这种情况下,我们只需要在显示数组之前反转 x 和 y 轴(轴号 0 和 1):

return image.swapaxes(0,1),out

我认为 technico 提供了一个很好的解决方案 - 只是有点依赖信息。假设 get_arr() 是 returns 像素数组的函数:

pixl_arr = get_arr()
pixl_arr = numpy.swapaxes(pixl_arr, 0, 1)
new_surf = pygame.pixelcopy.make_surface(pixl_arr)
screen.blit(new_surf, (dest_x, dest_y))

或者,如果您知道图像将始终具有相同的尺寸(如迭代视频或 gif 文件的帧),则重用相同的表面会更有效:

pixl_arr = get_arr()
pixl_arr = numpy.swapaxes(pixl_arr, 0, 1)
pygame.pixelcopy.array_to_surface(old_surf, pixl_arr)
screen.blit(old_surf, (dest_x, dest_y))

YMMV,但到目前为止这对我来说效果很好。