【问题标题】:Count cells of adjacent numpy regions计算相邻numpy区域的单元格
【发布时间】:2016-09-07 21:35:12
【问题描述】:

我正在寻找解决以下问题。我有一个 numpy 数组,它被标记为从 1 到 n 的区域。假设这是数组:

x = np.array([[1, 1, 1, 4], [1, 1, 2, 4], [1, 2, 2, 4], [5, 5, 3, 4]], np.int32)

array([[1, 1, 1, 4],
       [1, 1, 2, 4],
       [1, 2, 2, 4],
       [5, 5, 3, 4]])

区域是 numpy 数组中具有唯一值的组合单元格。所以在这个例子中 x 有 5 个区域;区域 1 由 5 个单元组成,区域 2 由 3 个单元组成,依此类推。 现在,我用以下代码行确定每个区域的相邻区域:

n = x.max()
tmp = np.zeros((n+1, n+1), bool)

# check the vertical adjacency
a, b = x[:-1, :], x[1:, :]
tmp[a[a!=b], b[a!=b]] = True

# check the horizontal adjacency
a, b = x[:, :-1], x[:, 1:]
tmp[a[a!=b], b[a!=b]] = True

# register adjacency in both directions (up, down) and (left,right)
result = (tmp | tmp.T)

result = result.astype(int)
np.column_stack(np.nonzero(result))
resultlist = [np.flatnonzero(row) for row in result[1:]]

这给了我每个区域及其相邻区域的列表:

[array([2, 4, 5], dtype=int64),
 array([1, 3, 4, 5], dtype=int64),
 array([2, 4, 5], dtype=int64),
 array([1, 2, 3], dtype=int64),
 array([1, 2, 3], dtype=int64)]

效果非常好。但是,我想计算每个相邻区域的单元格数量并返回此输出。因此,对于区域 2,在此示例中意味着总共 7 个相邻区域(三个 1、两个 4、一个 3 和一个 5)。因此:

  • 2 被 1 包围 43%
  • 2 被 5 包围 14 %
  • 2 被 3 包围 14%
  • 2 被 4 包围 29%

如何最好地调整上述代码以包含每个相邻区域的单元格数量? 非常感谢你们!

【问题讨论】:

  • 什么是区域?
  • 区域是 numpy 数组中具有唯一值的组合单元格。所以在这个例子中 x 有 5 个区域;区域 1 由 5 个单元组成,区域 2 由 3 个单元组成,以此类推。
  • 区域的形状必须是什么?相邻的数字 1 有六个,而不是五个。

标签: python arrays numpy


【解决方案1】:

这是一个使用 numpy_indexed 包的矢量化解决方案(注意;它不是在区域上矢量化,而是在像素上矢量化,假设 n_pixels >> n_regions 这样做很有用):

neighbors = np.concatenate([x[:, :-1].flatten(), x[:, +1:].flatten(), x[+1:, :].flatten(), x[:-1, :].flatten()])
centers   = np.concatenate([x[:, +1:].flatten(), x[:, :-1].flatten(), x[:-1, :].flatten(), x[+1:, :].flatten()])
valid = neighbors != centers

import numpy_indexed as npi
regions, neighbors_per_regions = npi.group_by(centers[valid], neighbors[valid])
for region, neighbors_per_region in zip(regions, neighbors_per_regions):
    print(region)
    unique_neighbors, neighbor_counts = npi.count(neighbors_per_region)
    print(unique_neighbors, neighbor_counts / neighbor_counts.sum() * 100)

或者对于在像素和区域上完全矢量化的解决方案:

(neighbors, centers), counts  = npi.count((neighbors[valid], centers[valid]))
region_group = group_by(centers)
regions, neighbors_per_region = region_group.sum(counts)
fractions = counts / neighbors_per_region[region_group.inverse]
for q in zip(centers, neighbors, fractions): print(q)

【讨论】:

  • 感谢您的回复!简洁而快速的方法,几乎​​可以工作。唯一的问题是它也计算自己的区域。如何将区域本身排除在与其邻居一起计算的范围之外?例如,现在区域 1 也将六个区域 1 单元格视为其邻居:1 (array([1, 2, 4, 5]), array([ 0.66666667, 0.22222222, 0.05555556, 0.05555556])) 再次感谢!您的解决方案总是很棒。
  • 啊,没想到!未经测试,但我认为这应该解决它:unique_neighbors, neighbor_counts = npi.count(n[n != region])
  • 确实解决了!你的 numpy-indexed 包真的很棒!再次感谢 Eelco 的快速回复和大力帮助 :)
  • 想想,分组前做过滤逻辑效率更高;类似于 selected = center.flatten() != neighbors.flatten() 的东西
  • 感谢您的加入。我今天在尺寸不等的较大数据集(6695 x 10000)上实现该函数时遇到了一个问题。然后,邻居和中心输出会生成 4 个具有邻居而不是 1 个的数组。如何在尺寸不等的图像上实现这一点?谢谢!
猜你喜欢
  • 2012-09-18
  • 1970-01-01
  • 2016-07-21
  • 1970-01-01
  • 2023-03-16
  • 2016-03-17
  • 2019-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多