Carnez Davis
Carnez Davis

Reputation: 63

Multidimensional Array and Magnitude of Gradient

I am new to python. I am trying to read an image into a multidimensional numpy array and compute the magnitude of the gradient, which should produce a single channel image. The dimensions after I compute the magnitude, however, is 700 x 900. Can anyone help me format the data, so I can receive a single channel image?

a = imread('20091016_tumor_26_18245948_1chop.png')
ndimage.gaussian_gradient_magnitude(a, 0.4, a)

Upvotes: 0

Views: 6134

Answers (2)

Carnez Davis
Carnez Davis

Reputation: 63

There are two version of this approach:

The first one works:

from Snaxel import Snaxel
from Snake import Snake
from get_snaxels import get_snaxels;
import numpy
import scipy
from pylab import imread, imshow, gray, mean
from matplotlib.pyplot import imsave

alpha = 1.0
beta = 0.0
gamma = -10.0
delta_y = 3
delta_x = 0

row_idx = 160
contour = [];

count = 0
for i in range(0, 1000):
    contour.append((row_idx, i))


snaxels, num_snaxels = get_snaxels(contour)
a = imread('synthesized_kymogram_2.png')
f = numpy.rot90(a, 2)
f = numpy.rot90(a, 2)


snake = Snake(snaxels, alpha, beta, delta_y, delta_x, f, gamma)
snake.MinimizeEnergy()

But, when I revise the following to:

from Snaxel import Snaxel
from Snake import Snake
from get_snaxels import get_snaxels;
import numpy
import scipy
from pylab import imread, imshow, gray, mean
from matplotlib.pyplot import imsave

alpha = 1.0
beta = 0.0
gamma = -10.0
delta_y = 3
delta_x = 0

row_idx = 160
contour = [];

count = 0
for i in range(0, 1000):
    contour.append((row_idx, i))


snaxels, num_snaxels = get_snaxels(contour)
a = imread('20091016_tumor_26_18245948_1chop.png')

g=ndimage.gaussian_gradient_magnitude(a, 0.4)

snake = Snake(snaxels, alpha, beta, delta_y, delta_x, g, gamma)
snake.MinimizeEnergy()

I get the following error:

if energy < min_energy:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

I thought the magnitude of the gradient would work. But, it does not? Does anyone know how to resolve it?

Upvotes: 0

askewchan
askewchan

Reputation: 46530

I think people are being confused by your terminology. A single channel image is a 2D array..., a multi-channel image would be a 3D array (extra dimension to store each channel). For example, a single channel image would be grayscale, but multi-channel would be color. For more information, see Channel (digital image)

If you want a scalar output, you would have to be more specific on how you want to reduce an image to a scalar. One simple example would be the norm of the array, as below, but this choice should depend on your use case.

a = imread('20091016_tumor_26_18245948_1chop.png')  # a 2d input image
g = ndimage.gaussian_gradient_magnitude(a, 0.4)  # a 2d image showing magnitude of the gradient in a

s = np.linalg.norm(g)  # the scalar norm of the gradient

In your comment you suggested that you'd tried

grad = numpy.gradient(a)
a = numpy.sqrt(grad.dot(grad)) 

The problem here, assuming you want a scalar in the end, is that many (if not most) functions within numpy, by default, operate on each element of the array. So, in the above code, gradient gives the gradient at each pixel

a.shape
#(H, W)
grad.shape
#(2, H, W)

Since the gradient itself is a vector,it actually adds to the dimensionality, so a 2d image becomes a 3d array.

sqrt and dot (in this case) each return an array of the same size as the input. If you use dot on two arrays, it is doing the matrix version of a.T * b Here, a and b are both the same shape. The output of the inner or dot product of a 1d or 2d array has the same width as the right hand side and same height as the left hand side, hence two square matrices give a square matrix.

Here are some examples:

a = Image.open('kinglet_bw.jpg')
plt.imshow(a)

a

for i, g in enumerate(np.gradient(a,3,3)):
    plt.subplot(121+i)
    plt.imshow(g)

g2

g = ndimage.gaussian_gradient_magnitude(a, 3)
plt.imshow(g)

g

Upvotes: 2

Related Questions