I am trying to determine the gradient image of a color image using skimage in python.
The method I am following is:
1) For each of the RGB bands calculate the gradient for each band. This results in 6 arrays, 2 for each color band. Each color band has a gradient in both x and y directions. (2 directions x 3 colors = 6 arrays).
2) To determine the gradient of the image, calculating the magnitude of each of the color bands as:
Gradient = ((Rx^2 + Ry^2) + (Gx^2 + Gy^2) + (Bx^2 + By^2))^0.5
But the result is very noisy and the gradient is unclear.
import numpy as np
import matplotlib.pyplot as plt
import scipy.ndimage as nd
import skimage.data as dt
img = dt.astronaut()
def gradient(img, x = True, y = True):
f1 = np.array([[-1,-2,-1], [0,0,0], [1,2,1]])
f2 = np.array([[-1,-2,-1], [0,0,0], [1,2,1]]).T
vert_gradient =nd.correlate(img, f1)
horz_gradient =nd.correlate(img, f2)
if x:
return(horz_gradient)
else:
return (vert_gradient)
Rx = gradient(img[:,:,0], y = False)
Ry = gradient(img[:,:,0], x = False)
Gx = gradient(img[:,:,1], y = False)
Gy = gradient(img[:,:,1], x = False)
Bx = gradient(img[:,:,2], y = False)
By = gradient(img[:,:,2], x = False)
grad = np.sqrt(np.square(Rx) + np.square(Ry)) + np.sqrt(np.square(Gx) + np.square(Gy)) + np.sqrt(np.square(Bx) + np.square(By))
grad = ((grad - grad.min()) / (grad.max() - grad.min())) * 255 # rescale for full dynamic range for 8 bit image
grad = grad.astype(np.uint8)
plt.subplot(1,2,1)
plt.imshow(img)
plt.subplot(1,2,2)
plt.imshow(grad)
plt.show()
In the gradient image we can see the color gradients, but they are not so clear and there is a lot of noise.
I have also tried smoothing out the noise on each color band before calculating the gradient.
How to improve this result without using OpenCv?
Find each channel's gradient separately like this
gradR = np.sqrt(np.square(Rx) + np.square(Ry))
gradG = np.sqrt(np.square(Gx) + np.square(Gy))
gradB = np.sqrt(np.square(Bx) + np.square(By))
make a new image
grad = np.dstack((gradR,gradG,gradB))