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

Don*_*per 2 python numpy image-processing vectorization

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
Run Code Online (Sandbox Code Playgroud)

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

我如何矢量化?

Han*_*rse 6

您可以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()
Run Code Online (Sandbox Code Playgroud)

图像输出具有可比性。对于一些400 x 400RGB 图像,我得到以下时间:

Duration loop:        0.21099094100000004
Duration vectorized:  0.004011090000000106
Run Code Online (Sandbox Code Playgroud)

希望有帮助!

----------------------------------------
System information
----------------------------------------
Platform:    Windows-10-10.0.16299-SP0
Python:      3.8.1
NumPy:       1.18.1
OpenCV:      4.1.2
----------------------------------------
Run Code Online (Sandbox Code Playgroud)