如何在numpy 2d数组中选择唯一元素的所有位置,并在其周围加上边框? [英] How to select all locations of unique elements in numpy 2d array with bounding box around them?

查看:166
本文介绍了如何在numpy 2d数组中选择唯一元素的所有位置,并在其周围加上边框?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a 2D numpy array I want to find the 'every' location of all the unique elements. We can find the unique elements using numpy.unique(numpyarray.). Here it comes the tricky part. Now I have to know all the locations for every unique element. Lets consider the following example.

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)

如何进行操作以及什么是存储和迭代值的合适方法.

How to do it and what could be a suitable way to store and iterate over the values.

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

It is to be noted that all the unique values will be adjacent to each other. The only gaps between them could only be zeros. Lets consider another variant

 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应该被忽略.

The zeoros on the boundaries are to be neglected.

非常感谢

推荐答案

简单,蛮力的方法是只使用numpy.where.

The simple, brute force way to do it is to just use 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) 

这对于带有零的示例同样适用.

This will work for the example with zeros, as well.

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

If the array is large, and you already have scipy around, you might consider using scipy.ndimage.find_objects instead, as @unutbu suggested.

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

In the particular case of your example, where your unique values are sequential integers, you can use find_objects directly. It expects an array where each sequential integer other than 0 represents an object that it needs to return the bounding box of. (0 is ignored, exactly as you want.) However, in general, you'll need to do a touch of pre-processing to convert arbitrary unique values to sequential integers.

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

find_objects retuns a list of tuples of slice objects. Honestly, these are probably exactly what you want, if you're wanting the bouding box. However, it will look a bit more messy to print out starting and stopping indicies.

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

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

This will look slightly different than you might expect. These are slice objects, so the "max" value will always be one higher than the "max" in the previous example. This is so that you can simply slice with the given tuple to get the data in question.

例如

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

如果您确实想要启动和停止,只需执行以下操作即可:

If you really want the starts and stops, just do something like this:

    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)

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

If your unique values are not sequential integers, you'll need to do a bit of pre-processing, as I mentioned before. You might do something like this:

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'

这篇关于如何在numpy 2d数组中选择唯一元素的所有位置,并在其周围加上边框?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆