I have written a simple code to add noise to image:
import cv2
from skimage.util import *
img = cv2.imread("./A/0030050944.jpg")
img = random_noise(img, mode='poisson', seed=42, clip=False)
cv2.imwrite("test.jpg", img)
But this only gives a blank black image.
Check this code. It adds gaussian , salt-pepper , poisson and speckle noise in an image.
Parameters
----------
image : ndarray
Input image data. Will be converted to float.
mode : str
One of the following strings, selecting the type of noise to add:
'gauss' Gaussian-distributed additive noise.
'poisson' Poisson-distributed noise generated from the data.
's&p' Replaces random pixels with 0 or 1.
'speckle' Multiplicative noise using out = image + n*image,where
n is uniform noise with specified mean & variance.
import numpy as np
import os
import cv2
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
From How to add noise (Gaussian/salt and pepper etc) to image in Python with OpenCV
possion noise
from PIL import Image
import numpy as np
from skimage.util import random_noise
im = Image.open("test.jpg")
# convert PIL Image to ndarray
im_arr = np.asarray(im)
# random_noise() method will convert image in [0, 255] to [0, 1.0],
# inherently it use np.random.normal() to create normal distribution
# and adds the generated noised back to image
noise_img = random_noise(im_arr, mode='possion', var=0.05**2)
noise_img = (255*noise_img).astype(np.uint8)
img = Image.fromarray(noise_img)
img.show()
Related
I want to demonstrate the Gaussian Kernel used in openCV. cv2.GaussianBlurr(img, kernel_size, sigma) for explanation purposes.
I know how to demonstrate the image which results after applying the blur, and that is not my objective here.
My objective is to demonstrate the kernel automatically for any used sigma, and any used kernel size!
I have seen a code(mentioned down) but I prefer to use something more related to instruction used in OpenCV, rather than just a general mathematical dependent approach.
The expected output kernel is something like this:
import cv2
import numpy as np
# Read Image
img_path = 'image.jpg'
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# Gaussian Blurr
Kernel = np.ones((15,15))
sigma = 2
Blurred_Image = cv2.GaussianBlur(img, (Kernel.shape[0], Kernel.shape[1]), sigma)
Gaussian Kernel Manual Code:
def dnorm(x, mu, sd):
return 1 / (np.sqrt(2 * np.pi) * sd) * np.e ** (-np.power((x - mu) / sd, 2) / 2)
def gaussian_kernel(size, sigma=1, verbose=False):
kernel_1D = np.linspace(-(size // 2), size // 2, size)
for i in range(size):
kernel_1D[i] = dnorm(kernel_1D[i], 0, sigma)
kernel_2D = np.outer(kernel_1D.T, kernel_1D.T)
kernel_2D *= 1.0 / kernel_2D.max()
if verbose:
plt.imshow(kernel_2D, interpolation='none',cmap='gray')
plt.title("Image")
plt.show()
return kernel_2D
Here is one way in Python/OpenCV.
- Read the input
- Create a delta image (one white pixel in the center of a black background)
- Blur the image
- List item
- Resize the image to enlarge it
- Stretch the image to full dynamic range
- Save the result
import cv2
import numpy as np
import skimage.exposure as exposure
# create delta image
dims = 30
dims2 = 30 // 2
delta = np.zeros((dims,dims,3), dtype=np.float32)
delta[dims2:dims2+1, dims2:dims2+1] = (255,255,255)
# blur image
blur = cv2.GaussianBlur(delta, (0,0), sigmaX=5, sigmaY=5)
# resize 16x
dims4x = dims * 16
resized = cv2.resize(blur, (dims4x,dims4x), interpolation = cv2.INTER_AREA)
# stretch to full dynamic range
result = exposure.rescale_intensity(resized, in_range='image', out_range=(0,255)).astype(np.uint8)
# save image
cv2.imwrite('delta.png',delta)
cv2.imwrite('gaussian_blur_view.png',result)
# show the images
cv2.imshow("delta", delta)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Delta image:
Result:
I wanted to understand the implementation of the Gaussian filter. In this code I implemented a Gaussian kernel and applied it to image with filter2D. But, instead of a blurred image, I only get a darker (for high variance value) and very bright (for low variance value). I tried a fixed np.ones(3,3)/2 for the kernel, and it successfully blurred the image. What might be the problem?
import cv2
import math
import numpy as np
filename = "lenna.png"
winname = "G Team Lets Go"
original = cv2.imread(filename)
cv2.namedWindow(winname)
def gaussian_blurr(image, variance, kernel_size):
def gaussian(x, y):
return (1 / (2 * np.pi * variance) * np.exp(-1 * ((math.pow(x, 2) + math.pow(y, 2)) / (2 * variance))))
kernel = np.zeros((kernel_size, kernel_size))
for x in range(-int(kernel_size/2), kernel_size-int(kernel_size/2)):
for y in range(-int(kernel_size/2), kernel_size-int(kernel_size/2)):
kernel[x+int(kernel_size/2), y+int(kernel_size/2)] = gaussian(x, y)
padding_size = int(kernel_size/2)
withBorder = cv2.copyMakeBorder(
image, padding_size, padding_size, padding_size, padding_size, cv2.BORDER_REPLICATE)
return cv2.filter2D(image, -1, kernel)
variance = 1
size = 3
def handle_variance(value):
if value == 0:
value = 1
variance = value/100
cv2.imshow(winname, gaussian_blurr(original, variance, size))
def handle_size(value):
if value == 0:
value = 1
size = value
cv2.imshow(winname, gaussian_blurr(original, variance, size))
cv2.createTrackbar("Variance", winname, 0, 500, handle_variance)
cv2.createTrackbar("Size", winname, 0, 5, handle_size)
cv2.imshow(winname, gaussian_blurr(original, 0.2, 3))
cv2.waitKey(0)
I'm trying to convert an image from a numpy array format to a PIL one. This is my code:
img = numpy.array(image)
row,col,ch= np.array(img).shape
mean = 0
# var = 0.1
# sigma = var**0.5
gauss = np.random.normal(mean,1,(row,col,ch))
gauss = gauss.reshape(row,col,ch)
noisy = img + gauss
im = Image.fromarray(noisy)
The input to this method is a PIL image. This method should add Gaussian noise to the image and return it as a PIL image once more.
Any help is greatly appreciated!
In my comments I meant that you do something like this:
import numpy as np
from PIL import Image
img = np.array(image)
mean = 0
# var = 0.1
# sigma = var**0.5
gauss = np.random.normal(mean, 1, img.shape)
# normalize image to range [0,255]
noisy = img + gauss
minv = np.amin(noisy)
maxv = np.amax(noisy)
noisy = (255 * (noisy - minv) / (maxv - minv)).astype(np.uint8)
im = Image.fromarray(noisy)
I got to know RAW images are interleaved and each pixel holds the value of each R,G,B component. So I have written below code to read the RGB pixel values and reshaped the image array to make it RGB image. After then I am converting the image to a binary one to process further. After conversion when I am trying to display the image it seems to contains noise. Can anyone help me in removing the noise?
Python version: 3.6
CODE:
from scipy import misc
from scipy import ndimage
import numpy as np
import matplotlib.pyplot as plt
import math
from PIL import Image
import rawpy
import imageio
def convert_to_binary(img):
threshold = 150
img[img <= 30] = 0
img[img > 30] = 255
return img
def sobel_test(im):
dx = ndimage.sobel(im, 0) # horizontal derivative
dy = ndimage.sobel(im, 1) # vertical derivative
mag = np.hypot(dx, dy) # magnitude
print(np.max(mag))
mag *= 255.0 / np.max(mag) # normalize (Q&D)
print(mag)
misc.imsave('sobel.jpg', mag)
return mag
A = np.fromfile("ABC.raw", dtype='int8', sep="")
A = np.reshape(A, (756, 1008, 3))
print("A.shape: %d", A.shape)
print("A: ", A)
print("A[0]: ", A[0])
img_gray = np.dot(A[..., :3], [0.30, 0.59, 0.11])
print("img_gray :", img_gray)
print("img_gray shape: ", img_gray.shape)
print("img_gray size: ", img_gray.size)
sob_img = sobel_test(img_gray)
binary_img = convert_to_binary(sob_img)
plt.imshow(binary_img, cmap="gray")
plt.show()
INPUT RAW Image: https://drive.google.com/open?id=12LcQZyYWMg9_6T_n3gjy7kBadRGNMDdr
Output Image
I am trying to implement the Wiener Filter to perform deconvolution on blurred image. My implementation is like this
import numpy as np
from numpy.fft import fft2, ifft2
def wiener_filter(img, kernel, K = 10):
dummy = np.copy(img)
kernel = np.pad(kernel, [(0, dummy.shape[0] - kernel.shape[0]), (0, dummy.shape[1] - kernel.shape[1])], 'constant')
# Fourier Transform
dummy = fft2(dummy)
kernel = fft2(kernel)
kernel = np.conj(kernel) / (np.abs(kernel) ** 2 + K)
dummy = dummy * kernel
dummy = np.abs(ifft2(dummy))
return np.uint8(dummy)
This implementation is based on the Wiki Page.
The TIFF image used is from : http://www.ece.rice.edu/~wakin/images/lena512color.tiff
But here is a PNG version:
I have a input image motion blurred by a diagonal kernel and some gaussian additive noise is added to it. The lena picture is 512x512 and the blurring kernel is 11x11.
When I apply my wiener_filter to this image the result is like this.
.
I think this deblurred image is not of good quality. So I would like to ask if my implementation is correct.
Update the way I add noise.
from scipy.signal import gaussian, convolve2d
def blur(img, mode = 'box', block_size = 3):
# mode = 'box' or 'gaussian' or 'motion'
dummy = np.copy(img)
if mode == 'box':
h = np.ones((block_size, block_size)) / block_size ** 2
elif mode == 'gaussian':
h = gaussian(block_size, block_size / 3).reshape(block_size, 1)
h = np.dot(h, h.transpose())
h /= np.sum(h)
elif mode == 'motion':
h = np.eye(block_size) / block_size
dummy = convolve2d(dummy, h, mode = 'valid')
return np.uint8(dummy), h
def gaussian_add(img, sigma = 5):
dummy = np.copy(img).astype(float)
gauss = np.random.normal(0, sigma, np.shape(img))
# Additive Noise
dummy = np.round(gauss + dummy)
# Saturate lower bound
dummy[np.where(dummy < 0)] = 0
# Saturate upper bound
dummy[np.where(dummy > 255)] = 255
return np.uint8(dummy)
Use skimage.restoration.wiener, which is usually used like:
>>> from skimage import color, data, restoration
>>> img = color.rgb2gray(data.astronaut())
>>> from scipy.signal import convolve2d
>>> psf = np.ones((5, 5)) / 25
>>> img = convolve2d(img, psf, 'same')
>>> img += 0.1 * img.std() * np.random.standard_normal(img.shape)
>>> deconvolved_img = restoration.wiener(img, psf, 1100)
I have also used it in: Deblur an image using scikit-image.
For data comparison, you can find a sample implementation of Wiener filtering and unsupervisived Wiener filtering at
http://scikit-image.org/docs/dev/auto_examples/plot_restoration.html
If you give your original image data, we may be able to help further.
EDIT: Original link seems to be down, try this one:
http://scikit-image.org/docs/dev/auto_examples/filters/plot_restoration.html
We could try unsupervised weiner too (deconvolution with a Wiener-Hunt approach, where the hyperparameters are automatically estimated, using a stochastic iterative process (Gibbs sampler), as described here):
deconvolved, _ = restoration.unsupervised_wiener(im, psf)