如何将 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.imread
和 pyGame
之间的差异吗?或者这是由于我的代码有问题吗?
还有其他方法吗?我阅读的大多数解决方案都涉及保存图形,然后使用“pyGame”读取它。
我的建议是使用pygame.transform
模块。有 flip
和 rotate
方法,您可以使用它们来进行转换。查阅相关文档。
我的建议是将输出图像保存到一个新的 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,但到目前为止这对我来说效果很好。
我正在编写一段代码,其中一部分是读取图像源并将其显示在屏幕上供用户交互。我还需要锐化的图像数据。我使用以下读取数据并将其显示在 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.imread
和 pyGame
之间的差异吗?或者这是由于我的代码有问题吗?
还有其他方法吗?我阅读的大多数解决方案都涉及保存图形,然后使用“pyGame”读取它。
我的建议是使用pygame.transform
模块。有 flip
和 rotate
方法,您可以使用它们来进行转换。查阅相关文档。
我的建议是将输出图像保存到一个新的 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,但到目前为止这对我来说效果很好。