首页 文章

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

提问于
浏览
7

我正在编写一段代码,其中一部分是读取图像源并将其显示在屏幕上供用户进行交互 . 我还需要锐化的图像数据 . 我使用以下内容读取数据并在 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”读取它 .

4 回答

  • 1

    每个lib都有自己的解释图像数组的方法 . 通过'旋转',我想你的意思是换位 . 这就是PyGame显示numpy数组的方式 . 有很多方法可以让它看起来“正确” . 实际上,甚至有很多方法可以显示数组,这使您可以完全控制通道表示等 . 在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 library(cv2.imread(filename)) . 使用openCV,您可以以BGR顺序打开图像作为标准,并且它具有许多转换功能 . 如果我没记错的话,当直接写入表面缓冲区时,BGR是24位的正确顺序,而32位表面的BGRA是正确的顺序 . 因此,您可以尝试将带有此功能的图像数组和blit放到屏幕上 .

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

    enter image description here

  • 1

    我的建议是使用 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))
    

    我不知道为什么会这样 . 这可能与轴从2d数组转移到pygame Surface 的顺序有关 .

  • 0

    我认为technico提供了一个很好的解决方案 - 只需要一点点信息 . 假设get_arr()是一个返回像素数组的函数:

    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,但到目前为止这对我来说效果很好 .

  • 1

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

    return image.swapaxes(0,1),out

相关问题