首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >快速将带标签的图像转换为{ label:[label]}的字典

快速将带标签的图像转换为{ label:[label]}的字典
EN

Stack Overflow用户
提问于 2015-09-24 04:33:17
回答 4查看 1.4K关注 0票数 7

假设我用scipy.ndimage.measurements.label标记了一个图像,如下所示:

代码语言:javascript
复制
[[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]]

收集属于每个标签的坐标的快速方法是什么?例如,类似于:

代码语言:javascript
复制
{ 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.nonzeronp.where)似乎都与标签的数量线性缩放,而使用nditer迭代每个图像元素明显地与标签图像的大小线性缩放。

一个小测试的结果是:

代码语言:javascript
复制
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)更快?

EN

回答 4

Stack Overflow用户

发布于 2015-09-24 06:06:24

这是一种可能性:

代码语言:javascript
复制
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。下面是一个示例运行:

代码语言:javascript
复制
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]])}
票数 4
EN

Stack Overflow用户

发布于 2015-09-24 05:12:35

您可以这样做(让img是您的原始nd.array)

代码语言:javascript
复制
res = {}
for i in np.unique(img)[1:]:
  x, y = np.where(a == i)
  res[i] = zip(list(x), list(y))

它会给你你想要的:

代码语言:javascript
复制
{
 1: [(0, 1), (1, 1), (2, 1)],
 2: [(4, 0), (4, 1), (5, 0), (5, 1)],
 3: [(3, 4)]
}

它是否会更快-取决于基准测试。

根据Warren的建议,我不需要使用unique,可以直接使用

代码语言:javascript
复制
res = {}
for i in range(1, num_labels + 1)
    x, y = np.where(a == i)
    res[i] = zip(list(x), list(y))
票数 2
EN

Stack Overflow用户

发布于 2015-09-24 05:20:37

试试这个:

代码语言:javascript
复制
>>> 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)]}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32748950

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档