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

2024-10-19 16:45:11 发布

您现在位置:Python中文网/ 问答频道 /正文

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

如何将其矢量化


Tags: inimageforoutputnp情况rangerandom
2条回答

不确定这是否会产生完全相同的结果-因为有一种可能性(非常小),你可以用盐击中一个像素,然后再用胡椒再次击中同一个像素-但我尝试了不同的方法。它还能产生半盐半胡椒,其他溶液只有在对大量样本进行平均时才会产生。也许节省的速度和内存值得不精确性—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.1p=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)

enter image description here

enter image description here

您可以使用附加的size参数调用^{},以获得整个随机浮点数组。然后,使用^{}boolean array indexing访问与其中一个条件匹配的所有像素

这就是我的解决方案,包括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
                    

相关问题 更多 >