2 回答

TA贡献1809条经验 获得超8个赞
您可以np.random.random
使用附加size
参数调用以获取整个随机浮点数组。然后,使用布尔数组索引来访问与条件之一匹配的所有像素np.where
。
这就是我的解决方案,包括用于图像加载和显示的OpenCV以及一些简单的性能分析:
import cv2
import numpy as np
import time
def sp_noise(image, prob):
output = np.zeros(image.shape, np.uint8)
thres = 1 - prob
for i in range(image.shape[0]):
for j in range(image.shape[1]):
rdn = np.random.random()
if rdn < prob:
output[i][j] = 0
elif rdn > thres:
output[i][j] = 255
else:
output[i][j] = image[i][j]
return output
def sp_noise_vec(image, prob):
output = image.copy()
thres = 1 - prob
rdn = np.random.random(image.shape[:2])
output[np.where(rdn < prob)] = 0
output[np.where(rdn > thres)] = 255
return output
img = cv2.imread('path/to/your/image.png')
tic = time.perf_counter()
out = sp_noise(img, 0.1)
toc = time.perf_counter()
print('Duration loop: ', toc - tic)
tic = time.perf_counter()
out_vec = sp_noise_vec(img, 0.1)
toc = time.perf_counter()
print('Duration vectorized: ', toc - tic)
cv2.imshow('img', img)
cv2.imshow('out', out)
cv2.imshow('out_vec', out_vec)
cv2.waitKey(0)
cv2.destroyAllWindows()
图像输出具有可比性。对于一些400 x 400RGB 图像,我得到以下时间:
Duration loop: 0.21099094100000004
Duration vectorized: 0.004011090000000106
希望有帮助!
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.8.1
NumPy: 1.18.1
OpenCV: 4.1.2
----------------------------------------

TA贡献1876条经验 获得超5个赞
不确定这是否会给出完全相同的结果——因为有可能(非常小)你可以用盐击中一个像素,然后再用胡椒再次击中相同的像素——但我尝试了一种不同的方法。它还准确地生成一半盐和一半胡椒,而其他解决方案往往只有在对大量样本进行平均时才会这样做。也许速度和内存节省值得不准确 - 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)
添加回答
举报