Python 如何使用numpy有效地生成脉冲噪声图像?

Python 如何使用numpy有效地生成脉冲噪声图像?,python,numpy,opencv,image-processing,Python,Numpy,Opencv,Image Processing,我一直在尝试使用以下代码创建有噪声的图像: def toImpulse(img, coef=1.2): # img - > 3dim numpy array, returns impulse image bmp = np.zeros(shape=(img.shape[0], img.shape[1], 1), dtype=np.float) for i in range(img.shape[0]): for j in range(img.shape[1]):

我一直在尝试使用以下代码创建有噪声的图像:

def toImpulse(img, coef=1.2): # img - > 3dim numpy array, returns impulse image
    bmp = np.zeros(shape=(img.shape[0], img.shape[1], 1), dtype=np.float)
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            bmp[i][j] = sum(img[i][j]) / 3
这里我对RGB通道求和,使图像为单通道?我想它可以写成numpy.sum()

但它在实时视频处理中显得非常缓慢。如何使用NumPy使其更高效?下面是函数工作的示例

您的第二个for循环可以替换为数组的总和中的
np。searchsorted

def toImpulse2(img, coef=1.2): # img - > 3dim numpy array, returns impulse image
    bmp = img.sum(axis=2)
    max_ = bmp.max() * coef
    cumsum = np.cumsum(bmp)
    repeats = int(cumsum[-1] / max_)
    final = np.zeros((img.shape[0] * img.shape[1], img.shape[2]))
    final[np.searchsorted(cumsum, np.arange(1, repeats + 1) * max_)] = 1
    return final.reshape(img.shape)

我使用
img.sum()
而不是
img.mean()
将所有计算保持为整数类型以提高精度。对于大图像,此代码和您的代码之间几乎没有什么区别,因为它是以浮点类型操作的。

您的代码在我的机器上需要539ms的时间。如果我使用Numpy计算3个颜色通道的平均值,并避免将零写入输出图像,因为它已初始化为零,如下所示:

def metoImpulse(img, coef=1.2):
    # Get mean of the 3 colour channels
    bmp = np.mean(img, axis=-1, dtype=np.float32)
    sum_ = 0
    max_ = np.amax(bmp)
    final = np.zeros_like(img[...,0])
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            sum_ += bmp[i][j]
            if sum_ >= coef * max_:
                final[i][j] = 1
                sum_ -= coef * max_
    return final
时间从539ms下降到257ms。如果我随后通过在函数前添加装饰器来使用Numba:

@jit(parallel=True)
def metoImpulse(img, coef=1.2):
   # Get mean of the 3 colour channels
   bmp = np.mean(img, axis=-1, dtype=np.float32)
   sum_ = 0
   max_ = np.amax(bmp)
   final = np.zeros_like(img[...,0])
   for i in range(img.shape[0]):
      for j in range(img.shape[1]):
         sum_ += bmp[i][j]
         if sum_ >= coef * max_:
            final[i][j] = 1
            sum_ -= coef * max_
   return final
时间从257ms下降到1.11ms

输入图像:

输出图像:


第一个函数可以简单地编写为,并且应该比for循环更有效:
返回np.sum(axis=2)/3
。对于代码的第二部分,我想不出更好的方法,因为您似乎正在进行条件累积和。一般来说,为了高效的代码,您应该避免使用显式for循环,而使用numpy的函数。当然
np.mean(axis=2)
可能会尝试
numba
第二部分。您可以尝试使用带有一个计数器的平面img(img.flat())数组。并使用变量k=coef*max_uuout FOR。您还可以删除
else final[i][j]=0
,因为它是用零初始化的。该代码不会生成任何形式的噪声,甚至不会生成随机数。看起来更像是一种抖动?
@jit(parallel=True)
def metoImpulse(img, coef=1.2):
   # Get mean of the 3 colour channels
   bmp = np.mean(img, axis=-1, dtype=np.float32)
   sum_ = 0
   max_ = np.amax(bmp)
   final = np.zeros_like(img[...,0])
   for i in range(img.shape[0]):
      for j in range(img.shape[1]):
         sum_ += bmp[i][j]
         if sum_ >= coef * max_:
            final[i][j] = 1
            sum_ -= coef * max_
   return final