假设我用scipy.ndimage.measurements.label标记了一个图像,如下所示:
[[0, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 3, 0],
[2, 2, 0, 0, 0, 0],
[2, 2, 0, 0, 0, 0]]收集属于每个标签的坐标的快速方法是什么?例如,类似于:
{ 1: [[0, 1], [1, 1], [2, 1]],
2: [[4, 0], [4, 1], [5, 0], [5, 1]],
3: [[3, 4]] }我正在处理大小约为15,000 x 5000像素的图像,每个图像大约有一半的像素被标记(即非零)。
与使用nditer遍历整个图像相比,对每个标签执行类似np.where(img == label)的操作会更快吗?
编辑:
哪种算法最快取决于带标签的图像相对于它有多少标签的图像有多大。Warren Weckesser和np.where/ BHAT IRSHAD的方法(基于np.nonzero和np.where)似乎都与标签的数量线性缩放,而使用nditer迭代每个图像元素明显地与标签图像的大小线性缩放。
一个小测试的结果是:
size: 1000 x 1000, num_labels: 10
weckesser ... 0.214357852936s
dali ... 0.650229930878s
nditer ... 6.53645992279s
size: 1000 x 1000, num_labels: 100
weckesser ... 0.936990022659s
dali ... 1.33582305908s
nditer ... 6.81486487389s
size: 1000 x 1000, num_labels: 1000
weckesser ... 8.43906402588s
dali ... 9.81333303452s
nditer ... 7.47897100449s
size: 1000 x 1000, num_labels: 10000
weckesser ... 100.405524015s
dali ... 118.17239809s
nditer ... 9.14583897591s因此,问题变得更加具体:
对于标签数量在sqrt(size(image))数量级的标签图像,有没有一种算法可以收集标签坐标,比迭代每个图像元素(即使用nditer)更快?
发布于 2015-09-24 06:06:24
这是一种可能性:
import numpy as np
a = np.array([[0, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 3, 0],
[2, 2, 0, 0, 0, 0],
[2, 2, 0, 0, 0, 0]])
# If the array was computed using scipy.ndimage.measurements.label, you
# already know how many labels there are.
num_labels = 3
nz = np.nonzero(a)
coords = np.column_stack(nz)
nzvals = a[nz[0], nz[1]]
res = {k:coords[nzvals == k] for k in range(1, num_labels + 1)}我称这个脚本为get_label_indices.py。下面是一个示例运行:
In [97]: import pprint
In [98]: run get_label_indices.py
In [99]: pprint.pprint(res)
{1: array([[0, 1],
[1, 1],
[2, 1]]),
2: array([[4, 0],
[4, 1],
[5, 0],
[5, 1]]),
3: array([[3, 4]])}发布于 2015-09-24 05:12:35
您可以这样做(让img是您的原始nd.array)
res = {}
for i in np.unique(img)[1:]:
x, y = np.where(a == i)
res[i] = zip(list(x), list(y))它会给你你想要的:
{
1: [(0, 1), (1, 1), (2, 1)],
2: [(4, 0), (4, 1), (5, 0), (5, 1)],
3: [(3, 4)]
}它是否会更快-取决于基准测试。
根据Warren的建议,我不需要使用unique,可以直接使用
res = {}
for i in range(1, num_labels + 1)
x, y = np.where(a == i)
res[i] = zip(list(x), list(y))发布于 2015-09-24 05:20:37
试试这个:
>>> z
array([[0, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 3, 0],
[2, 2, 0, 0, 0, 0],
[2, 2, 0, 0, 0, 0]])
>>> {i:zip(*np.where(z==i)) for i in np.unique(z) if i}
{1: [(0, 1), (1, 1), (2, 1)], 2: [(4, 0), (4, 1), (5, 0), (5, 1)], 3: [(3, 4)]}https://stackoverflow.com/questions/32748950
复制相似问题