在 Numpy 中逐像素迭代两个图像(随机条件)

import random

def sp_noise(image,prob):

    '''

    Add salt and pepper noise to image

    prob: Probability of the noise

    '''

    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 = 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

这就是我想要达到的目标。我知道这个函数不使用矢量化,但我不知道在这种情况下如何摆脱循环。如果有像素值的条件,那将是微不足道的。但在这种情况下,索引或像素值没有条件,我只需要保留像素值,或者根据随机变量的值将其设置为 0 或 1。


我如何矢量化它?


慕田峪4524236
浏览 66回答 2
2回答

海绵宝宝撒

您可以np.random.random使用附加size参数调用以获取整个随机浮点数组。然后,使用布尔数组索引来访问与条件之一匹配的所有像素np.where。这就是我的解决方案,包括用于图像加载和显示的OpenCV以及一些简单的性能分析:import cv2import numpy as npimport timedef sp_noise(image, prob):&nbsp; &nbsp; output = np.zeros(image.shape, np.uint8)&nbsp; &nbsp; thres = 1 - prob&nbsp; &nbsp; for i in range(image.shape[0]):&nbsp; &nbsp; &nbsp; &nbsp; for j in range(image.shape[1]):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rdn = np.random.random()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if rdn < prob:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output[i][j] = 0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elif rdn > thres:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output[i][j] = 255&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output[i][j] = image[i][j]&nbsp; &nbsp; return outputdef sp_noise_vec(image, prob):&nbsp; &nbsp; output = image.copy()&nbsp; &nbsp; thres = 1 - prob&nbsp; &nbsp; rdn = np.random.random(image.shape[:2])&nbsp; &nbsp; output[np.where(rdn < prob)] = 0&nbsp; &nbsp; output[np.where(rdn > thres)] = 255&nbsp; &nbsp; return outputimg = 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:&nbsp; &nbsp; &nbsp; &nbsp; 0.21099094100000004Duration vectorized:&nbsp; 0.004011090000000106希望有帮助!----------------------------------------System information----------------------------------------Platform:&nbsp; &nbsp; Windows-10-10.0.16299-SP0Python:&nbsp; &nbsp; &nbsp; 3.8.1NumPy:&nbsp; &nbsp; &nbsp; &nbsp;1.18.1OpenCV:&nbsp; &nbsp; &nbsp; 4.1.2----------------------------------------

慕运维8079593

不确定这是否会给出完全相同的结果——因为有可能(非常小)你可以用盐击中一个像素,然后再用胡椒再次击中相同的像素——但我尝试了一种不同的方法。它还准确地生成一半盐和一半胡椒,而其他解决方案往往只有在对大量样本进行平均时才会这样做。也许速度和内存节省值得不准确 - YMMV :-)首先确定有多少像素会受到噪声的影响,称之为N。然后生成 N/2 对 [x,y] 坐标并将输出图像中的相应像素设置为黑色,然后生成另外 N/2 对 [x,y] 坐标并将它们设置为白色。import numpy as npdef me(image,prob):&nbsp;&nbsp; &nbsp; h, w = image.shape[:2]&nbsp; &nbsp; # Number of noise affected pixels&nbsp; &nbsp; N = int(w * h * prob)&nbsp; &nbsp; # Half salt&nbsp; &nbsp; image[np.random.randint(0,h,int(N/2)), np.random.randint(0,w,int(N/2))] = 255&nbsp; &nbsp; # Half pepper&nbsp; &nbsp; image[np.random.randint(0,h,int(N/2)), np.random.randint(0,w,int(N/2))] = 0&nbsp;&nbsp; &nbsp; return image&nbsp;# Make solid grey start imageimage = np.full((400,400), 128, dtype=np.uint8)和p=0.1,p=0.01我得到:%timeit me(image,0.1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;296 µs ± 2.48 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)%timeit me(image,0.01)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;42.2 µs ± 933 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python