Python(scikit-image):确定遮罩区域中最常见颜色的最高效方法

问题描述 投票:0回答:1

我正在修改一款策略游戏,并且有两个 RGB 图像。一个定义了地图上的省份区域,每个省份都有一种独特的颜色。另一张图像定义了地图的地形。

我有一个 python 脚本,可以比较这两个图像,通过检查每个省份最常见的地形颜色来确定每个省份的地形类型。

例如,我可能会检查颜色省份(0, 0, 255),并发现其区域在地形图上完全充满了草原像素。

我目前这样做的具体方式是这样的:

from skimage import io
import numpy

# Takes an RGB map of shape x, y, and colour channels, and converts it to a 2D array of shape x, y, where each item in the 2D array is an int referring to the colour
# it represents, as indexed in the returned unique colours list.
def get_inverse_map(map, to_tuples = True):
    original_map_shape = (map.shape[0], map.shape[1])
    flattened_map = map.reshape(-1, map.shape[2])
    unique_map_cols, first_occurances, map_inverses, index_counts = numpy.unique(flattened_map, return_index = True, return_inverse = True, return_counts = True, axis = 0)
    unflattened_inverse_map = map_inverses.reshape(original_map_shape)

    if to_tuples:
        unique_map_tuples = [tuple(col) for col in unique_map_cols]
        return unflattened_inverse_map, unique_map_tuples, index_counts
    else:
        return unflattened_inverse_map, unique_map_cols, index_counts


province_map = io.imread(self.province_map_dir)
terrain_map = io.imread(self.terrain_map_dir)

inverse_province_map, unique_province_cols = get_inverse_map(province_map)[ : 2]
inverse_terrain_map, unique_terrain_cols = get_inverse_map(terrain_map)[ : 2]

for p in unique_province_cols:
    province_mask = inverse_province_map == p
    province_terrain_pixels = inverse_terrain_map[province_mask]

    occurances = numpy.bincount(province_terrain_pixels)
    mode_index = numpy.argmax(occurances) # This is the most common index of the colours in the terrain map that occur within province_mask
  1. 我将图像从 RGB 数组(形状:x, x, 3)转换为索引图(形状:x, x, 1),以便更快进行比较。
  2. 我得到了我想要评估的省份的面具。
  3. 我获取地形图中属于省内的像素 地图。
  4. 我使用 bincount 和 argmax 来查找最常见的一个。

因为我不能总是保证只有一种地形颜色会在一个省的边界内(有时我会在边缘上绘制),所以我需要找到最常见的颜色,而不是只检查一个像素。

我在非常大的图像上执行此操作,因此尽管我使用索引图来加快速度,但它仍然需要时间。大部分时间似乎都浪费在了

get_inverse_map
上,大概是
numpy.unique
,尽管我不确定。

有没有更快的方法来解决这个问题?

python performance scikit-image area overlapping
1个回答
0
投票

您的方法的问题是迭代每个省份的整个地图。我的解决方案只执行一次。

假设你知道:

  • 省份数量 -
    N
    (如果不假设最大省份数量)
  • 可能的地形颜色数量 -
    C

做:

  1. 创建 2d numpy 数组

    province_terrain_stats
    来累积统计数据,
    N x C
    的大小,每列代表

  2. 迭代整个地图,在每个像素处读取其省份 idx 和颜色 idx。在

    province_terrain_stats
    中正确位置的统计数据中添加 1。 您可能需要创建一些
    color2idx
    辅助地图。 重要提示:使用
    numba
    包在整个地图上编写此循环。如果您想使用此解决方案获得良好的性能,这是必须的。

  3. 对于

    province_terrain_stats
    中的每个省份,使用
    np.argmax

    查找最常见的地形
© www.soinside.com 2019 - 2024. All rights reserved.