为了账号安全,请及时绑定邮箱和手机立即绑定

找到像素区域质心的更快方法

找到像素区域质心的更快方法

小唯快跑啊 2022-01-18 21:32:19
对于一个游戏,我制作了一个由像素组成的区域地图,每个区域都有不同的颜色。从那里,我想在每个地区添加名字。出于视觉目的,我想将名称放在该区域的质心上。因此,我使用 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)


查看完整回答
反对 回复 2022-01-18
  • 1 回答
  • 0 关注
  • 229 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信