我试图添加噪音到图像中,以模仿真实世界的噪音产生的高ISO设置的相机。
from skimage.util import random_noise
import random
val = random.uniform(0.036, 0.107)
noisy_img = random_noise(im_arr, mode='gaussian', var=val ** 2)
noisy_img = (255 * noisy_img).astype(np.uint8)
该代码运行良好,但噪声颗粒的大小始终为1像素。我真的想要不同大小的噪音颗粒。我怎样才能做到这一点?
发布于 2022-04-10 21:28:22
模拟高ISO环境下不同晶粒尺寸的噪声是很有挑战性的。
原因之一是,变化的晶粒的来源不是纯粹的物理效应。
其中一些颗粒来自于数字降噪(图像处理)的伪像,不同的相机和摄像机是不同的。
我想到了一个相对简单的解决方案:
resolutions.
需要进行大量的调整--选择分辨率,将不同的噪声设置到不同的分辨率,选择调整大小的插值方法。
我不认为这正是你想要的,但它应用了“不同粒度的噪音”,并可能给你一个线索。
代码示例:
from skimage.util import random_noise
from skimage.io import imsave
from skimage.transform import resize
import random
import numpy as np
im_arr = np.full((256, 320), 0.5) # Original image - use gray image for testing
rows, cols = im_arr.shape
val = 0.036 #random.uniform(0.036, 0.107) # Use constant variance (for testing).
# Full resolution
noise_im1 = np.zeros((rows, cols))
noise_im1 = random_noise(noise_im1, mode='gaussian', var=val**2, clip=False)
# Half resolution
noise_im2 = np.zeros((rows//2, cols//2))
noise_im2 = random_noise(noise_im2, mode='gaussian', var=(val*2)**2, clip=False) # Use val*2 (needs tuning...)
noise_im2 = resize(noise_im2, (rows, cols)) # Upscale to original image size
# Quarter resolution
noise_im3 = np.zeros((rows//4, cols//4))
noise_im3 = random_noise(noise_im3, mode='gaussian', var=(val*4)**2, clip=False) # Use val*4 (needs tuning...)
noise_im3 = resize(noise_im3, (rows, cols)) # What is the interpolation method?
noise_im = noise_im1 + noise_im2 + noise_im3 # Sum the noise in multiple resolutions (the mean of noise_im is around zero).
noisy_img = im_arr + noise_im # Add noise_im to the input image.
noisy_img = np.round((255 * noisy_img)).clip(0, 255).astype(np.uint8)
imsave('noisy_img.png', noisy_img)
结果:
发布于 2022-04-11 03:12:48
你的问题意味着你想要空间相关的噪声,这样相邻的像素就可以共享一些信息。如果您并不真正关心相关结构是什么样子,您可以使用一个简单的平滑内核来生成粒度更粗的噪声。
实现这一目标的途径之一是:
from skimage.data import shepp_logan_phantom
from skimage.util import random_noise
from scipy.ndimage import correlate
import numpy as np
# Granularity = 1
im_arr = shepp_logan_phantom()
val = 0.05
noisy_img = random_noise(im_arr, mode='gaussian', var=val)
# Correlated noise to increase granularity
# Generate random noise like skimage's random_noise does
noise = np.random.normal(scale=np.sqrt(val), size=im_arr.shape)
# Create a smoothing kernel
weights = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]]) / 5
# Apply it to the noise
noise_corr = correlate(noise, weights)
# Apply noise to image and clip
noisy_img_corr = np.clip(im_arr + noise_corr, 0, 1)
fig, (ax1, ax2) = plt.subplots(ncols=2)
ax1.imshow(noisy_img)
ax1.set_title("Uncorrelated noise")
ax1.axis("off")
ax2.imshow(noisy_img_corr)
ax2.set_title("Correlated noise")
ax2.axis("off")
或者,如果你知道相机里的噪音是从哪里来的,你也可以根据第一原理建立更好的噪声模型。这里有一些想法:https://graphics.stanford.edu/courses/cs178-10/lectures/noise-27apr10-150dpi-med.pdf。
发布于 2022-04-11 03:41:30
Rotem的答案是最好的实现。
我(最初的海报)使用以下代码来扩展他对彩色图像的实现,并使用PIL作为导入,以防以后有人需要它:
from skimage.transform import resize
import numpy as np
from skimage.util import random_noise
from PIL import Image
def gen_noise_mask(rows, cols):
val = 0.036 # random.uniform(0.036, 0.107) # Use constant variance (for testing).
# Full resolution
noise_im1 = np.zeros((rows, cols))
noise_im1 = random_noise(noise_im1, mode='gaussian', var=val ** 2, clip=False)
# Half resolution
noise_im2 = np.zeros((rows // 2, cols // 2))
noise_im2 = random_noise(noise_im2, mode='gaussian', var=(val * 2) ** 2, clip=False) # Use val*2 (needs tuning...)
noise_im2 = resize(noise_im2, (rows, cols)) # Upscale to original image size
# Quarter resolution
noise_im3 = np.zeros((rows // 4, cols // 4))
noise_im3 = random_noise(noise_im3, mode='gaussian', var=(val * 4) ** 2, clip=False) # Use val*4 (needs tuning...)
noise_im3 = resize(noise_im3, (rows, cols)) # What is the interpolation method?
noise_im = noise_im1 + noise_im2 + noise_im3 # Sum the noise in multiple resolutions (the mean of noise_im is around zero).
return noise_im
def noiseGenerator(im):
im_arr = np.asarray(im)
rows, cols, depth = im_arr.shape
rgba_array = np.zeros((rows, cols, depth), 'float64')
for d in range(0, depth):
rgba_array[..., d] += gen_noise_mask(rows, cols)
noisy_img = im_arr / 255 + rgba_array # Add noise_im to the input image.
noisy_img = np.round((255 * noisy_img)).clip(0, 255).astype(np.uint8)
return Image.fromarray(noisy_img)
https://stackoverflow.com/questions/71818076
复制相似问题