对于一个游戏,我制作了一个由像素组成的区域地图,每个区域都有不同的颜色。从那里,我想在每个地区添加名字。出于视觉目的,我想将名称放在该区域的质心上。因此,我使用 PIL 将图像转换为单个大矩阵。我建立了一个类来记录每个区域的质心数据,并收集在字典中。然后,我遍历像素来处理质心。这种方法非常慢,对于 2400 x 1100 的地图大约需要一分钟。territory_map = numpy.array([ [0, 0, 0, 1, 0, 0, 0], [0, 2, 2, 1, 0, 0, 0], [2, 2, 1, 1, 3, 3, 3], [2, 0, 0, 1, 3, 0, 0],])centroid_data = {}class CentroidRecord(object): def __init__(self, x, y): super(CentroidRecord, self).__init__() self.x = float(x) self.y = float(y) self.volume = 1 def add_mass(self, x, y): # new_x = (old_x * old_volume + x) / (old_volume + 1), # therefore new_x = old_x + (x - old_x) / v, # for v = volume + 1. self.volume += 1 self.x += (x - self.x) / self.volume self.y += (y - self.y) / self.volumefor y in range(territory_map.shape[0]): for x in range(territory_map.shape[1]): cell = territory_map[y][x] if cell == 0: continue if cell not in centroid_data: centroid_data[cell] = CentroidRecord(x, y) else: centroid_data[cell].add_mass(x, y)for area in centroid_data: data = centroid_data[area] print(f"{area}: ({data.x}, {data.y})")这应该打印以下内容:1: (2.8, 1.6)2: (0.8, 1.8)3: (4.75, 2.25)有没有更快的方法来做到这一点?
1 回答
噜噜哒
TA贡献1784条经验 获得超7个赞
一种颜色的质心的每个坐标只是该颜色的所有点坐标的平均值。因此,我们可以使用一个dict推导:
import numpy as np
n_colours = territory_map.max()
{i: tuple(c.mean() for c in np.where(territory_map.T == i))
for i in range(1, n_colours + 1)}
输出:
{1: (2.8, 1.6),
2: (0.8, 1.8),
3: (4.75, 2.25)}
请注意,我们需要进行转置,因为行(y 坐标)在列(x 坐标)之前numpy。
随机生成的数据所花费的时间:
81.6 ms ± 5.36 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
添加回答
举报
0/150
提交
取消