在 pygame 中,我有一个表面:
im = pygame.image.load('foo.png').convert_alpha()
im = pygame.transform.scale(im, (64, 64))
如何获取图像的灰度副本,或将图像数据转换为灰度?我有麻木。
使用 Surfarray,并使用 numpy 或 Numeric 对其进行过滤:
def grayscale(self, img):
arr = pygame.surfarray.array3d(img)
#luminosity filter
avgs = [[(r*0.298 + g*0.587 + b*0.114) for (r,g,b) in col] for col in arr]
arr = numpy.array([[[avg,avg,avg] for avg in col] for col in avgs])
return pygame.surfarray.make_surface(arr)
最简单的方法是遍历图像中的所有像素并调用 .get_at(...) 和 .set_at(...)。
这会很慢,所以为了回答你关于使用 NumPy 的隐含建议,请查看http://www.pygame.org/docs/tut/surfarray/SurfarrayIntro.html。概念和大部分代码是相同的。
经过大量研究,我想出了这个解决方案,因为这个问题的答案对于我想要这个功能来说太慢了:
def greyscale(surface: pygame.Surface):
start = time.time() # delete me!
arr = pygame.surfarray.array3d(surface)
# calulates the avg of the "rgb" values, this reduces the dim by 1
mean_arr = np.mean(arr, axis=2)
# restores the dimension from 2 to 3
mean_arr3d = mean_arr[..., np.newaxis]
# repeat the avg value obtained before over the axis 2
new_arr = np.repeat(mean_arr3d[:, :, :], 3, axis=2)
diff = time.time() - start # delete me!
# return the new surface
return pygame.surfarray.make_surface(new_arr)
我使用 time.time() 来计算这种方法的时间成本,因此对于 (800, 600, 3) 数组,它需要:0.026769161224365234
s 才能运行。
正如您所指出的,这是一个保留亮度的变体:
def greyscale(surface: pygame.Surface):
arr = pygame.surfarray.pixels3d(surface)
mean_arr = np.dot(arr[:,:,:], [0.216, 0.587, 0.144])
mean_arr3d = mean_arr[..., np.newaxis]
new_arr = np.repeat(mean_arr3d[:, :, :], 3, axis=2)
return pygame.surfarray.make_surface(new_arr)