我有一组3D数组,每个数组代表一个图像。我想找到给定坐标在所有数组中包含非黑色像素的出现次数。
result = np.zeros_like(list_of_arrays[0])
for array in list_of_arrays:
for (y, x) in np.argwhere(array.any(-1)):
result[y][x] += 1
return result
如何才能最好地改善这种天真的实施方式?如果我知道如何将第三维转换为0或1,我可以复制每个数组然后添加它们以获得我的答案。问题是我不知道如何进行转换。
两张3x3照片的示例
# picture 1
[[[ 208., 208., 208.],
[ 0., 0., 0.],
[ 110., 110., 110.]],
[[ 161., 161., 161.],
[ 140., 140., 140.],
[ 251., 251., 251.]],
[[ 0., 0., 0.],
[ 55., 55., 55.],
[ 26., 26., 26.]]]
# picture 2
[[[ 88., 88., 88.],
[ 140., 140., 140.],
[ 0., 0., 0.]],
[[ 18., 18., 18.],
[ 112., 112., 112.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 195., 195., 195.],
[ 5., 5., 5.]]]
# what I'd like
[[[ 2., 2., 2.],
[ 1., 1., 1.],
[ 1., 1., 1.]],
[[ 2., 2., 2.],
[ 2., 2., 2.],
[ 1., 1., 1.]],
[[ 0., 0., 0.],
[ 2., 2., 2.],
[ 2., 2., 2.]]]
答案 0 :(得分:2)
假设这两个图像是名为pic1
和pic2
的numpy数组:
pic1 = np.array(
[[[ 208., 208., 208.],
[ 0., 0., 0.],
[ 110., 110., 110.]],
[[ 161., 161., 161.],
[ 140., 140., 140.],
[ 251., 251., 251.]],
[[ 0., 0., 0.],
[ 55., 55., 55.],
[ 26., 26., 26.]]]
)
pic2 = np.array(
[[[ 88., 88., 88.],
[ 140., 140., 140.],
[ 0., 0., 0.]],
[[ 18., 18., 18.],
[ 112., 112., 112.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 195., 195., 195.],
[ 5., 5., 5.]]]
)
您可以使用np.array([pic1, pic2])
创建这些图像的numpy数组,或者如果您已经将图像放在列表中np.array(list_of_arrays)
。然后,对这个四维数组分别对每个元素应用逻辑运算,检查每个元素是否为非零。最后,对指定axis=0
:
# Get a numpy array of images
images = np.array([pic1, pic2]) # or np.array(list_of_arrays)
# Check for nonzero values and sum along the relevant axis
result = (images != 0).sum(axis=0)
array([[[2, 2, 2],
[1, 1, 1],
[1, 1, 1]],
[[2, 2, 2],
[2, 2, 2],
[1, 1, 1]],
[[0, 0, 0],
[2, 2, 2],
[2, 2, 2]]])
如果图像已经在列表中,那么这种方法可能没有其他方法那么快。也就是说,如果您在第一次创建图像集时可以选择数据结构,并且可以使用numpy数组,那么这是最快的。
答案 1 :(得分:1)
由于黑色由0
表示,您可以使用array.astype('bool')
将数组转换为布尔值,以便黑色变为False
,其他每种颜色变为True
。将这些数组与sum
组合在一起会将它们转换回整数,而True
会转换为1
,这样您最终会得到每个坐标处的非黑色像素数:
result = sum(ar.astype('bool') for ar in list_of_arrays)
作为数据类型转换的替代方法,您可以使用numpy.minimum
对图像进行阈值处理:
result = sum(np.minimum(ar, 1) for ar in list_of_arrays)
编辑:对于速度至关重要的情况,我已经进行了一项比较上述两种方法与ohruunuruus的基准比较:
>>> ar = [np.array([[ 208., 208., 208.],
[ 0., 0., 0.],
[ 110., 110., 110.]]), np.array([[ 161., 161., 161.],
[ 140., 140., 140.],
[ 251., 251., 251.]]), np.array([[ 0., 0., 0.],
[ 55., 55., 55.],
[ 26., 26., 26.]])]
>>> from time import time
>>> def f1(arrays):
... return sum(np.minimum(a, 1) for a in arrays)
...
>>> def f2(arrays):
... return sum(a.astype('bool') for a in arrays)
...
>>> def f3(arrays):
... return (np.array(arrays) != 0).sum(axis=0)
...
>>> def timeIt(func):
... start = time()
... for i in range(1000000):
... func(ar)
... stop = time()
... return stop-start
...
>>> timeIt(f1)
12.203268051147461
>>> timeIt(f2)
16.594016790390015
>>> timeIt(f3)
18.328339099884033
结果可能因图像的数量和大小不同而不同。