Не уверен, что это даст точно такой же результат - поскольку есть вероятность (очень мала), что вы можете ударить пиксель солью, а затем снова тот же пиксель снова перцем - но я попробовал другой подход. Он также генерирует ровно половину соли и половину перца, что обычно делают другие растворы только при усреднении по большому количеству образцов. Возможно, скорость и экономия памяти стоят неточностей - YMMV: -)
Сначала определите, сколько пикселей будет подвержено шуму, назовите его N
. Затем сгенерируйте N / 2 пары координат [x, y] и установите соответствующий пиксель в выходном изображении черным, затем сгенерируйте еще N / 2 пары координат [x, y] и установите их на белый.
import numpy as np
def me(image,prob):
h, w = image.shape[:2]
# Number of noise affected pixels
N = int(w * h * prob)
# Half salt
image[np.random.randint(0,h,int(N/2)), np.random.randint(0,w,int(N/2))] = 255
# Half pepper
image[np.random.randint(0,h,int(N/2)), np.random.randint(0,w,int(N/2))] = 0
return image
# Make solid grey start image
image = np.full((400,400), 128, dtype=np.uint8)
С p=0.1
и p=0.01
я получаю:
%timeit me(image,0.1)
296 µs ± 2.48 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit me(image,0.01)
42.2 µs ± 933 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)