Python 是否有一个“问题”;“边界框”;函数(具有非零值的切片)用于以NumPy为单位的数据数组?
我正在处理通过numpy.array()创建的数组,我需要在画布上绘制点来模拟图像。因为在包含有意义数据的数组的中心部分有很多零值,所以我想“修剪”数组,删除只包含零的列和只包含零的行 因此,我想知道一些本机numpy函数,甚至是一段代码片段,用于“修剪”或找到一个“边界框”,仅对包含数组一部分的数据进行切片 (因为这是一个概念性的问题,我没有写任何代码,如果我应该写的话,很抱歉,我很新鲜,可以在SO发帖。) 感谢您阅读以下内容:Python 是否有一个“问题”;“边界框”;函数(具有非零值的切片)用于以NumPy为单位的数据数组?,python,arrays,numpy,trim,bounding,Python,Arrays,Numpy,Trim,Bounding,我正在处理通过numpy.array()创建的数组,我需要在画布上绘制点来模拟图像。因为在包含有意义数据的数组的中心部分有很多零值,所以我想“修剪”数组,删除只包含零的列和只包含零的行 因此,我想知道一些本机numpy函数,甚至是一段代码片段,用于“修剪”或找到一个“边界框”,仅对包含数组一部分的数据进行切片 (因为这是一个概念性的问题,我没有写任何代码,如果我应该写的话,很抱歉,我很新鲜,可以在SO发帖。) 感谢您阅读以下内容: empty_cols = sp.all(array == 0,
empty_cols = sp.all(array == 0, axis=0)
empty_rows = sp.all(array == 0, axis=1)
生成的数组将是一维布尔数组。从两端对其进行循环以找到“边界框”。这应该可以做到:
from numpy import array, argwhere
A = array([[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]])
B = argwhere(A)
(ystart, xstart), (ystop, xstop) = B.min(0), B.max(0) + 1
Atrim = A[ystart:ystop, xstart:xstop]
下面的代码(来自)在我的测试中运行得最快:
def bbox2(img):
rows = np.any(img, axis=1)
cols = np.any(img, axis=0)
ymin, ymax = np.where(rows)[0][[0, -1]]
xmin, xmax = np.where(cols)[0][[0, -1]]
return img[ymin:ymax+1, xmin:xmax+1]
使用
argwhere
接受的答案有效,但运行速度较慢。我的猜测是,这是因为argwhere
分配了一个巨大的索引输出数组。我在一个大的2D阵列上进行了测试(一个1024 x 1024的图像,大约有一个50x100的非零区域)。应该避免在numpy阵列上循环。循环仅为1D,因此顺序为n,而不是n^2。没什么大不了的。顺序是正确的,甚至不需要在整个数组宽度上进行循环,但是python循环包含各种额外的步骤,比如类型检查。在这个1D示例中:python循环运行速度慢25倍,以完成相同的任务!如果不知道图像的大小、数量或算法的应用(计算机视觉?),我就说不出这种加速有多大意义。太好了!只要注意可读性,您就可以执行(ystart,xstart),(ystop,xstop)=B.min(0),B.max(0)+1
,然后简单地用Atrim=a[ystart:ystop,xstart:xstop]索引a
。当然,它是完全等效的,但无论如何,我觉得它更可读。这一个很好,您使用的示例正是我将使用的典型数组(只是更大)。我不知道函数argwhere,现在我要做作业了。谢谢@保罗..谢谢,你能帮我:-)有没有一种方法可以对任何数组维度执行此操作?@Naomi当然。只需扩展本例中的模式,在ystart
和xstart
之后添加zstart
3个DIM,并继续添加更多维度。请参阅bbox2函数。。。如果有许多行/列完全用零填充,并且只有少量集群数据,那么速度会快得多。我发现这个答案更像python!谢谢注意,在完全黑色图像的边缘情况下,此代码可能会生成错误。您必须验证这两个np.where()
调用都不会返回空数组。这太棒了!你知道如何用周期性边界条件来扩展它吗?@Tropilio我不知道你所说的周期性边界条件是什么意思。但是,如果您希望找到多个连续真值的“blob”,那么像这样的方法可能不起作用。相反,要查找任意blob,我将使用OpenCV connectedComponents()函数: