5

在 pygame 中,我有一个表面:

im = pygame.image.load('foo.png').convert_alpha()
im = pygame.transform.scale(im, (64, 64))

如何获取图像的灰度副本,或将图像数据转换为灰度?我有麻木。

4

3 回答 3

5

使用 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)
于 2012-05-21T22:43:53.150 回答
2

最简单的方法是遍历图像中的所有像素并调用 .get_at(...) 和 .set_at(...)。

这会很慢,所以为了回答你关于使用 NumPy 的隐含建议,请查看http://www.pygame.org/docs/tut/surfarray/SurfarrayIntro.html。概念和大部分代码是相同的。

于 2012-05-18T05:39:14.420 回答
2

经过大量研究,我想出了这个解决方案,因为这个问题的答案对于我想要这个功能来说太慢了:

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.026769161224365234s 才能运行。

正如您所指出的,这是一个保留亮度的变体:

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)
于 2021-01-27T12:51:06.663 回答