I followed the most upvoted answer to a question regarding adding noise to an image. However it doesn't work for me. I just want to observe different noise effects on image while using Python How to add noise (Gaussian/salt and pepper etc) to image in Python with OpenCV
From what I know, images are something of uint8 type? I'm not certain if this type can take decimals.
The salt and pepper part don't work either
from numpy import shape, asarray
import numpy as np
import cv2
from PIL import Image
def noisy(noise_typ,image):
if noise_typ == "gauss":
row,col,ch= image.shape
mean = 0
var = 0.1
sigma = var**0.5
gauss = np.random.normal(mean,sigma,(row,col,ch))
gauss = gauss.reshape(row,col,ch)
noisy = image + gauss
return noisy
elif noise_typ == "s&p":
row,col,ch = image.shape
s_vs_p = 0.5
amount = 0.004
out = np.copy(image)
# Salt mode
num_salt = np.ceil(amount * image.size * s_vs_p)
coords = [np.random.randint(0, i - 1, int(num_salt))
for i in image.shape]
out[coords] = 1
# Pepper mode
num_pepper = np.ceil(amount* image.size * (1. - s_vs_p))
coords = [np.random.randint(0, i - 1, int(num_pepper))
for i in image.shape]
out[coords] = 0
return out
elif noise_typ == "poisson":
vals = len(np.unique(image))
vals = 2 ** np.ceil(np.log2(vals))
noisy = np.random.poisson(image * vals) / float(vals)
return noisy
elif noise_typ =="speckle":
row,col,ch = image.shape
gauss = np.random.randn(row,col,ch)
gauss = gauss.reshape(row,col,ch)
noisy = image + image * gauss
return noisy
pic = Image.open('obamaface1.jpg')
pic = pic.convert('RGB')
pixels = asarray(pic)
image = Image.fromarray(pixels)
target = noisy('speckle', pixels)
target = Image.fromarray(target)
print(target)
The last line is to just see what is output by the terminal. It's output is
File "C:\Users\Jerome Ariola\AppData\Local\Programs\Python\Python36\lib\site-packages\PIL\Image.py", line 2647, in fromarray
raise TypeError("Cannot handle this data type")
TypeError: Cannot handle this data type
Commenting target = Image.fromarray(target)
gives me:
[[[ 10.03013352 7.53745105 11.03977542]
[ 9.38952149 7.81507808 11.53212491]
[ 9.76439692 7.88213107 11.47620008]
...
[ 6.76471119 5.09559321 5.9144036 ]
[ 7.34123162 4.92342273 6.31726796]
[255.13791218 253.89755922 255.15403824]]
[[ 9.90775807 8.49642977 10.86023707]
[ 9.71078442 7.94264649 11.18820572]
[ 9.91127254 8.15716707 11.04770154]
...
[ 7.05173864 4.89094663 5.67662439]
[ 7.10166986 5.47480635 6.11892638]
[255.03879603 254.07485578 254.88072098]]
[[ 9.81995678 7.55439474 11.08609859]
[ 10.32135236 7.5301714 11.03612056]
[ 10.17215819 8.09537629 11.30984933]
...
[ 7.13999574 5.12009845 7.8678079 ]
[ 7.31635614 5.1527127 8.23318054]
[255.12283461 254.01880276 254.76894074]]
...
[[ 19.72596723 22.29694693 20.95524912]
[ 19.30898519 21.61944993 20.85653566]
[ 20.45174165 20.55101246 21.1739277 ]
...
[ 13.89796331 11.73865315 12.50874487]
[ 14.13985843 11.97177032 12.80855176]
[255.04963076 254.23626115 254.75904336]]
[[ 19.17915912 21.2224852 18.37260714]
[ 19.1068802 20.2797369 17.96846182]
[ 20.37263348 20.23856465 18.02893703]
...
[ 14.48307596 12.46348446 15.43437954]
[ 14.11840104 12.35783324 14.64863437]
[254.99657596 253.95241488 255.34200558]]
[[ 20.03354477 22.02402748 18.45595882]
[ 19.74202893 22.59472663 19.19910502]
[ 21.96931817 22.22425014 19.59694792]
...
[ 14.68256917 12.37915145 15.07832362]
[ 14.25010143 12.45545202 14.65549651]
[254.96105357 254.17655349 255.29863654]]]
I thought I'd also rewrite it, e.g. from image.shape
to np.shape(image)
def noisify(type, target):
if type == 'gauss':
row,col, ch = np.shape(target)
mean = 0
var = 0.1
sigma = var**0.5
gauss = np.random.normal(mean, sigma, (row,col,ch))
noise = target + gauss
return noise
elif type == 'sap':
row, col, ch = np.shape(target)
s_vs_p = 0.5
amount = 0.004
out = np.copy(target)
#salt
num_salt = np.ceil(amount * np.size(target) * s_vs_p)
coords = [np.random.randint(0,i-1, int(num_salt))
for i in np.shape(target)]
out[coords] = 1
#pepper
num_pepper = np.ceil(amount* np.size(target) * (1. - s_vs_p))
coords = [np.random.randint(0,i-1, int(num_pepper))
for i in np.shape(target)]
out[coords] = 0
return out
elif type == 'poisson':
vals = len(np.unique(target))
vals = 2 ** np.ceil(np.log2(vals))
noise = np.random.poisson(target * vals) / float(vals)
return noise
elif type == 'speckle':
row, col, ch = np.shape(target)
gauss = np.random.randn(row,col,ch)
gauss = np.reshape(gauss,(row,col,ch))
noise = target + target * gauss
return noise
Any help would be appreciated.
Here's a vectorized approach using OpenCV + skimage.util.random_noise
. You can experiment with noise modes such as localvar
, pepper
, s&p
, and speckle
to obtain the desired result. You can set the proportion of noise with the amount
parameter. Here's an example using s&p
with amount=0.011
:
Input image
Result
With amount=0.051
:
import cv2
import numpy as np
from skimage.util import random_noise
# Load the image
image = cv2.imread('1.png', 0)
# Add salt-and-pepper noise to the image
noise = random_noise(image, mode='s&p', amount=0.011)
# The above function returns a floating-point image in the range [0, 1]
# so need to change it to 'uint8' with range [0,255]
noise = np.array(255 * noise, dtype=np.uint8)
cv2.imshow('noise',noise)
cv2.imwrite('noise.png',noise)
cv2.waitKey()