Numpy 如何在pygame中制作曲面的灰度副本?

Numpy 如何在pygame中制作曲面的灰度副本?,numpy,pygame,Numpy,Pygame,在pygame中,我有一个曲面: im = pygame.image.load('foo.png').convert_alpha() im = pygame.transform.scale(im, (64, 64)) 如何获取图像的灰度副本,或将图像数据转换为灰度?我有numpy。最简单的方法是迭代图像中的所有像素并调用.get_at(…)和.set_at(…) 这将是相当缓慢的,所以在回答你关于使用NumPy的暗示时,请看。概念和大部分代码是相同的。使用Surfarray,并使用numpy或

在pygame中,我有一个曲面:

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

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

最简单的方法是迭代图像中的所有像素并调用.get_at(…)和.set_at(…)


这将是相当缓慢的,所以在回答你关于使用NumPy的暗示时,请看。概念和大部分代码是相同的。

使用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)

经过大量研究,我提出了这个解决方案,因为对这个问题的回答太慢了,我不想让这个功能:

def灰度(表面:pygame.surface):
开始=时间。时间()#删除我!
arr=pygame.surfarray.array3d(曲面)
#计算“rgb”值的平均值,这将使dim减小1
平均值=np.平均值(平均值,轴=2)
#将标注从2恢复到3
mean_arr3d=mean_arr[…,np.newaxis]
#在轴2上重复之前获得的平均值
新arr=np.重复(平均arr3d[:,:,:],3,轴=2)
diff=time.time()-开始#删除我!
#返回新曲面
return pygame.surfarray.make_surface(新的_arr)
我使用time.time()来计算这种方法的时间开销,因此对于(800600,3)数组,它需要:
0.026769161224365234
s才能运行

正如您所指出的,这里有一个保持亮度的变体:

def灰度(表面:pygame.surface):
arr=pygame.surfarray.pixels3d(曲面)
平均值=np.dot(arr[:,:,:],[0.216,0.587,0.144])
mean_arr3d=mean_arr[…,np.newaxis]
新arr=np.重复(平均arr3d[:,:,:],3,轴=2)
return pygame.surfarray.make_surface(新的_arr)

如果使用.pixels3d而不是.array3d,则可以避免将所有数据复制到新曲面中。要使用相同的逻辑加速此操作:
arr=arr.dot([0.298,0.587,0.114])[:,:,无]。重复(3,axis=2);返回pygame.surfarry.make_surface(arr)
。在我的(800x600)测试图像上,这一速度提高了2个数量级以上。虽然图像转换为灰度,但阵列形状在三维仍有3个通道,我们如何摆脱通道?