从3D numpy像素阵列中删除空的“行"和“列" [英] Remove empty 'rows' and 'columns' from 3D numpy pixel array
问题描述
我本质上想用numpy裁剪图像-我有一个3维numpy.ndarray
对象,即:
I essentially want to crop an image with numpy—I have a 3-dimension numpy.ndarray
object, ie:
[ [0,0,0,0], [255,255,255,255], ....]
[0,0,0,0], [255,255,255,255], ....] ]
我要删除空白的地方,在上下文中,空白是[0,0,0,0]
的整个行或整个列.
where I want to remove whitespace, which, in context, is known to be either entire rows or entire columns of [0,0,0,0]
.
在此示例中,让每个像素只是一个数字,我试图做到这一点:
Letting each pixel just be a number for this example, I'm trying to essentially do this:
鉴于此:*选择了一个稍微复杂一点的例子来澄清
Given this: * chose a slightly more complex example to clarify
[ [0,0,0,0,0,0]
[0,0,1,1,1,0]
[0,1,1,0,1,0]
[0,0,0,1,1,0]
[0,0,0,0,0,0]]
[ [0,0,0,0,0,0]
[0,0,1,1,1,0]
[0,1,1,0,1,0]
[0,0,0,1,1,0]
[0,0,0,0,0,0]]
我正在尝试创建它:
[ [0,1,1,1],
[1,1,0,1],
[0,0,1,1] ]
[ [0,1,1,1],
[1,1,0,1],
[0,0,1,1] ]
我可以通过循环强行执行此操作,但是从直觉上来说,我觉得numpy可以做到这一点.
I can brute force this with loops, but intuitively I feel like numpy has a better means of doing this.
推荐答案
通常,您希望研究scipy.ndimage.label
和scipy.ndimage.find_objects
来提取满足条件的连续区域的边界框.
In general, you'd want to look into scipy.ndimage.label
and scipy.ndimage.find_objects
to extract the bounding box of contiguous regions fulfilling a condition.
但是,在这种情况下,您可以使用普通"的numpy相当容易地做到这一点.
However, in this case, you can do it fairly easily with "plain" numpy.
我将假设您在这里有一个nrows x ncols x nbands
数组. nbands x nrows x ncols
的另一种约定也很常见,因此请看一下数组的形状.
I'm going to assume you have a nrows x ncols x nbands
array here. The other convention of nbands x nrows x ncols
is also quite common, so have a look at the shape of your array.
考虑到这一点,您可能会执行类似的操作:
With that in mind, you might do something similar to:
mask = im == 0
all_white = mask.sum(axis=2) == 0
rows = np.flatnonzero((~all_white).sum(axis=1))
cols = np.flatnonzero((~all_white).sum(axis=0))
crop = im[rows.min():rows.max()+1, cols.min():cols.max()+1, :]
对于您的2D示例,它看起来像:
For your 2D example, it would look like:
import numpy as np
im = np.array([[0,0,0,0,0,0],
[0,0,1,1,1,0],
[0,1,1,0,1,0],
[0,0,0,1,1,0],
[0,0,0,0,0,0]])
mask = im == 0
rows = np.flatnonzero((~mask).sum(axis=1))
cols = np.flatnonzero((~mask).sum(axis=0))
crop = im[rows.min():rows.max()+1, cols.min():cols.max()+1]
print crop
让我们详细介绍一下2D示例.
Let's break down the 2D example a bit.
In [1]: import numpy as np
In [2]: im = np.array([[0,0,0,0,0,0],
...: [0,0,1,1,1,0],
...: [0,1,1,0,1,0],
...: [0,0,0,1,1,0],
...: [0,0,0,0,0,0]])
好的,现在让我们创建一个满足我们条件的布尔数组:
Okay, now let's create a boolean array that meets our condition:
In [3]: mask = im == 0
In [4]: mask
Out[4]:
array([[ True, True, True, True, True, True],
[ True, True, False, False, False, True],
[ True, False, False, True, False, True],
[ True, True, True, False, False, True],
[ True, True, True, True, True, True]], dtype=bool)
此外,请注意~
运算符在布尔数组上的作用与logical_not
一样:
Also, note that the ~
operator functions as logical_not
on boolean arrays:
In [5]: ~mask
Out[5]:
array([[False, False, False, False, False, False],
[False, False, True, True, True, False],
[False, True, True, False, True, False],
[False, False, False, True, True, False],
[False, False, False, False, False, False]], dtype=bool)
考虑到这一点,要查找所有元素均为假的行,我们可以对各列求和:
With that in mind, to find rows where all elements are false, we can sum across columns:
In [6]: (~mask).sum(axis=1)
Out[6]: array([0, 3, 3, 2, 0])
如果没有元素为True,我们将得到0.
If no elements are True, we'll get a 0.
同样,要查找所有元素均为假的列,我们可以跨行求和:
And similarly to find columns where all elements are false, we can sum across rows:
In [7]: (~mask).sum(axis=0)
Out[7]: array([0, 1, 2, 2, 3, 0])
现在,我们需要做的是找到所有不为零的第一个和最后一个.在这种情况下,np.flatnonzero
比nonzero
容易一点:
Now all we need to do is find the first and last of these that are not zero. np.flatnonzero
is a bit easier than nonzero
, in this case:
In [8]: np.flatnonzero((~mask).sum(axis=1))
Out[8]: array([1, 2, 3])
In [9]: np.flatnonzero((~mask).sum(axis=0))
Out[9]: array([1, 2, 3, 4])
然后,您可以根据最小/最大非零元素轻松切出区域:
Then, you can easily slice out the region based on min/max nonzero elements:
In [10]: rows = np.flatnonzero((~mask).sum(axis=1))
In [11]: cols = np.flatnonzero((~mask).sum(axis=0))
In [12]: im[rows.min():rows.max()+1, cols.min():cols.max()+1]
Out[12]:
array([[0, 1, 1, 1],
[1, 1, 0, 1],
[0, 0, 1, 1]])
这篇关于从3D numpy像素阵列中删除空的“行"和“列"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!