我有两个2d numpy数组(图像)。 由 图像 定义的第一个是在像素(i,j)处存储运动的总和
第二个由 nbCameras 定义,存储可以在此像素(i,j)处看到移动的摄像机数量
我想创建第三个图像 imgFinal ,它只存储像素(i,j)的值和它的邻居(3 x 3)蒙版,如果可以看到像素(i,j)的相机数量大于1.
现在我使用两个for循环,这不是最好的方法。我想提高计算的速度,但我还没有找到最好的方法。 此外,我有点被阻止,因为我想要转发像素的邻居(i,j)
我也试过使用bumpy.vectorize,但在这种情况下我可以保留像素的邻居。
提高此功能的最佳方法是什么?
感谢您的帮助!
maskWidth = 3
dstCenterMask = int( (maskWidth - 1) / 2)
imgFinal = np.zeros((image.shape),dtype = np.float32)
for j in range(dstCenterMask,image.shape[0] - dstCenterMask):
for i in range(dstCenterMask,image.shape[1] - dstCenterMask):
if nbCameras[j,i] > 1
imgFinal[j - dstCenterMask : j + dstCenterMask + 1, i - dstCenterMask : i + dstCenterMask + 1] =
image[j - dstCenterMask : j + dstCenterMask + 1, i - dstCenterMask : i + dstCenterMask + 1]
答案 0 :(得分:3)
使用skimage.morphology的binary_dilation函数,这非常优雅。它将采用二进制数组,并将任何真实像素扩展为真值(或任何其他大小)的3x3网格。这也应该处理边缘的情况。我认为你的实施没有。
使用这个掩码很容易计算imgFinal
from skimage.morphology import binary_dilation, square
mask = binary_dilation(nbCameras > 1, square(maskWidth))
imgFinal = np.where(mask, image, 0)
square(3)
只是np.ones((3,3))
扩张的示例使用以更好地阐明它的作用:
In [27]: a
Out[27]:
array([[ 1., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 1., 0.],
[ 0., 0., 0., 0., 0.]])
In [28]: binary_dilation(a, square(3))
Out[28]:
array([[1, 1, 0, 0, 0],
[1, 1, 0, 0, 0],
[0, 0, 1, 1, 1],
[0, 0, 1, 1, 1],
[0, 0, 1, 1, 1]], dtype=uint8)
答案 1 :(得分:1)
选项1:尝试以矢量化方式重写代码。您可以使用这样的3x3模板进行卷积:
import numpy as np
from scipy.signal import convolve2d
image = np.random.random((100,100))
nbCameras = np.abs(np.random.normal(size=(100,100)).round())
maskWidth = 3
mask = np.ones((maskWidth, maskWidth))
visibilityMask = (nbCameras>1).astype(np.float)
visibilityMask = convolve2d(visibilityMask, mask, mode="same").astype(np.bool)
imgFinal = image.copy()
imgFinal[~visibilityMask] *= 0
import matplotlib.pyplot as plt
for i, (im, title) in enumerate([(image, "image"),
(nbCameras, "nbCameras"),
(visibilityMask, "visibilityMask"),
(imgFinal, "imgFinal")]):
plt.subplot(2,2,i+1)
plt.title(title)
plt.imshow(im, cmap=plt.cm.gray)
plt.show()
这将导致此情节:
选项2:使用Numba。这使用了先进的即时优化技术,特别适用于加速循环。
答案 2 :(得分:1)
这不能处理数组边缘的摄像头,但你的代码也不会处理:
import numpy as np
from numpy.lib.stride_tricks import as_strided
rows, cols, mask_width = 10, 10, 3
mask_radius = mask_width // 2
image = np.random.rand(rows, cols)
nb_cameras = np.random.randint(3 ,size=(rows, cols))
image_view = as_strided(image, shape=image.shape + (mask_width, mask_width),
strides=image.strides*2)
img_final = np.zeros_like(image)
img_final_view = as_strided(img_final,
shape=img_final.shape + (mask_width, mask_width),
strides=img_final.strides*2)
copy_mask = nb_cameras[mask_radius:-mask_radius,
mask_radius:-mask_radius] > 1
img_final_view[copy_mask] = image_view[copy_mask]
运行上面的代码后:
>>> nb_cameras
array([[0, 2, 1, 0, 2, 0, 1, 2, 1, 0],
[0, 1, 1, 1, 1, 2, 1, 1, 2, 1],
[1, 2, 2, 2, 1, 2, 1, 0, 2, 0],
[0, 2, 2, 0, 1, 2, 1, 0, 1, 0],
[1, 2, 0, 1, 2, 0, 1, 0, 0, 2],
[2, 0, 1, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 2, 2, 0, 1, 1, 1, 0, 0],
[0, 0, 1, 0, 1, 0, 1, 0, 2, 2],
[0, 1, 0, 1, 1, 2, 1, 1, 2, 2],
[2, 2, 0, 1, 0, 0, 1, 2, 1, 0]])
>>> np.round(img_final, 1)
array([[ 0. , 0. , 0. , 0. , 0.7, 0.5, 0.6, 0.5, 0.6, 0.9],
[ 0.1, 0.6, 1. , 0.2, 0.3, 0.6, 0. , 0.2, 0.9, 0.9],
[ 0.2, 0.3, 0.3, 0.5, 0.2, 0.3, 0.4, 0.1, 0.7, 0.5],
[ 0.9, 0.1, 0.7, 0.8, 0.2, 0.9, 0.9, 0.1, 0.3, 0.3],
[ 0.8, 0.8, 1. , 0.9, 0.2, 0.5, 1. , 0. , 0. , 0. ],
[ 0.2, 0.3, 0.5, 0.4, 0.6, 0.2, 0. , 0. , 0. , 0. ],
[ 0. , 0.2, 1. , 0.2, 0.8, 0. , 0. , 0.7, 0.9, 0.6],
[ 0. , 0.2, 0.9, 0.9, 0.3, 0.4, 0.6, 0.6, 0.3, 0.6],
[ 0. , 0. , 0. , 0. , 0.8, 0.8, 0.1, 0.7, 0.4, 0.4],
[ 0. , 0. , 0. , 0. , 0. , 0.5, 0.1, 0.4, 0.3, 0.9]])
管理边缘的另一个选择是使用scipy.ndimage
中的卷积函数:
import scipy.ndimage
mask = scipy.ndimage.convolve(nb_cameras > 1, np.ones((3,3)),
mode='constant') != 0
img_final[mask] = image[mask]
>>> np.round(img_final, 1)
array([[ 0.6, 0.8, 0.7, 0.9, 0.7, 0.5, 0.6, 0.5, 0.6, 0.9],
[ 0.1, 0.6, 1. , 0.2, 0.3, 0.6, 0. , 0.2, 0.9, 0.9],
[ 0.2, 0.3, 0.3, 0.5, 0.2, 0.3, 0.4, 0.1, 0.7, 0.5],
[ 0.9, 0.1, 0.7, 0.8, 0.2, 0.9, 0.9, 0.1, 0.3, 0.3],
[ 0.8, 0.8, 1. , 0.9, 0.2, 0.5, 1. , 0. , 0.3, 0.8],
[ 0.2, 0.3, 0.5, 0.4, 0.6, 0.2, 0. , 0. , 0.7, 0.6],
[ 0.2, 0.2, 1. , 0.2, 0.8, 0. , 0. , 0.7, 0.9, 0.6],
[ 0. , 0.2, 0.9, 0.9, 0.3, 0.4, 0.6, 0.6, 0.3, 0.6],
[ 0.4, 1. , 0.8, 0. , 0.8, 0.8, 0.1, 0.7, 0.4, 0.4],
[ 0.9, 0.5, 0.8, 0. , 0. , 0.5, 0.1, 0.4, 0.3, 0.9]])