python-如何在numpy 2d数组中选择唯一元素的所有位置,并用包围框包围它们?

我有一个二维的numpy数组,我想找到所有唯一元素的“每个”位置.我们可以使用numpy.unique(numpyarray.)找到唯一的元素.这是棘手的部分.现在,我必须知道每个唯一元素的所有位置.让我们考虑以下示例.

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

结果应该是

1, (0,0),(1,1)
2, (0,2),(1,2)
3, (2,0),(3,1)
4, (2,2),(3,3)

如何做到这一点以及什么是存储和迭代值的合适方法.

应当注意,所有唯一值将彼此相邻.它们之间的唯一差距只能是零.让我们考虑另一个变体

 array([[1, 0, 1, 2, 2],\
        [1, 0, 1, 2, 2],\
        [3, 0, 3, 4, 4],\
        [3, 0, 3, 4, 4]])

结果应该是

1, (0,0),(1,2)
2, (0,3),(1,4)
3, (2,0),(3,2)
4, (2,3),(3,4)

边界上的zeoros将被忽略.

非常感谢

最佳答案
一种简单,蛮力的方法是使用numpy.where.

例如,如果您只需要边界框:

import numpy as np

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

for val in np.unique(x):
    rows, cols = np.where(x == val)
    rowstart, rowstop = np.min(rows), np.max(rows)
    colstart, colstop = np.min(cols), np.max(cols)
    print val, (rowstart, colstart), (rowstop, colstop) 

这也适用于带有零的示例.

如果数组很大,并且已经有了scipy,则可以考虑使用scipy.ndimage.find_objects,如@unutbu建议的那样.

在示例的特定情况下,其中唯一值是连续整数,则可以直接使用find_objects.它期望一个数组,其中每个非0的连续整数代表一个需要返回其边界框的对象. (完全忽略0,就可以将其忽略.)但是,通常,您需要进行一些预处理,以将任意唯一值转换为顺序整数.

find_objects重新调整切片对象的元组列表.老实说,如果您需要绑定框,这些可能正是您想要的.但是,打印出起始和终止指标看起来会有些混乱.

import numpy as np
import scipy.ndimage as ndimage

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

for i, item in enumerate(ndimage.find_objects(x), start=1):
    print i, item

这看起来可能与您预期的稍有不同.这些是切片对象,因此“ max”值将始终比上一个示例中的“ max”高一个.这样一来,您可以简单地对给定的元组进行切片以获取有问题的数据.

例如.

for i, item in enumerate(ndimage.find_objects(x), start=1):
    print i, ':'
    print x[item], '\n'

如果您确实想要开始和停止,请执行以下操作:

    for i, (rowslice, colslice) in enumerate(ndimage.find_objects(x), start=1):
        print i, 
        print (rowslice.start, rowslice.stop - 1),
        print (colslice.start, colslice.stop - 1)

如前所述,如果您的唯一值不是连续的整数,则需要进行一些预处理.您可能会执行以下操作:

import numpy as np
import scipy.ndimage as ndimage

x = np.array([[1.1, 0.0, 1.1, 0.9, 0.9],
              [1.1, 0.0, 1.1, 0.9, 0.9],
              [3.3, 0.0, 3.3, 4.4, 4.4],
              [3.3, 0.0, 3.3, 4.4, 4.4]])
ignored_val = 0.0
labels = np.zeros(data.shape, dtype=np.int)

i = 1
for val in np.unique(x):
    if val != ignored_val:
        labels[x == val] = i
        i += 1

# Now we can use the "labels" array as input to find_objects
for i, item in enumerate(ndimage.find_objects(labels), start=1):
    print i, ':'
    print x[item], '\n'

转载注明原文:python-如何在numpy 2d数组中选择唯一元素的所有位置,并用包围框包围它们? - 代码日志